Move the function/array conversion for ParmVarDecl's from Sema::ParseIdentifierExpr()
to Sema::ParseParamDeclarator(). After discussing this with Chris, we decided this approach has more immediate benefit (though we loose some information in the AST). The comment below should describe more (if interested). llvm-svn: 40907
This commit is contained in:
parent
a47f7d7cfd
commit
773df5cf30
|
|
@ -465,8 +465,31 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
|
||||||
|
|
||||||
// FIXME: Handle storage class (auto, register). No declarator?
|
// FIXME: Handle storage class (auto, register). No declarator?
|
||||||
// TODO: Chain to previous parameter with the prevdeclarator chain?
|
// TODO: Chain to previous parameter with the prevdeclarator chain?
|
||||||
ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II,
|
|
||||||
QualType::getFromOpaquePtr(PI.TypeInfo),
|
// Perform the default function/array conversion (C99 6.7.5.3p[7,8]).
|
||||||
|
// Doing the promotion here has a win and a loss. The win is the type for
|
||||||
|
// both Decl's and DeclRefExpr's will match (a convenient invariant for the
|
||||||
|
// code generator). The loss is the orginal type isn't preserved. For example:
|
||||||
|
//
|
||||||
|
// void func(int parmvardecl[5]) { // convert "int [5]" to "int *"
|
||||||
|
// int blockvardecl[5];
|
||||||
|
// sizeof(parmvardecl); // size == 4
|
||||||
|
// sizeof(blockvardecl); // size == 20
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// For expressions, all implicit conversions are captured using the
|
||||||
|
// ImplicitCastExpr AST node (we have no such mechanism for Decl's).
|
||||||
|
//
|
||||||
|
// FIXME: If a source translation tool needs to see the original type, then
|
||||||
|
// we need to consider storing both types (in ParmVarDecl)...
|
||||||
|
//
|
||||||
|
QualType parmDeclType = QualType::getFromOpaquePtr(PI.TypeInfo);
|
||||||
|
if (const ArrayType *AT = parmDeclType->getAsArrayType())
|
||||||
|
parmDeclType = Context.getPointerType(AT->getElementType());
|
||||||
|
else if (parmDeclType->isFunctionType())
|
||||||
|
parmDeclType = Context.getPointerType(parmDeclType);
|
||||||
|
|
||||||
|
ParmVarDecl *New = new ParmVarDecl(PI.IdentLoc, II, parmDeclType,
|
||||||
VarDecl::None, 0);
|
VarDecl::None, 0);
|
||||||
|
|
||||||
// If this has an identifier, add it to the scope stack.
|
// If this has an identifier, add it to the scope stack.
|
||||||
|
|
|
||||||
|
|
@ -73,32 +73,6 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
|
||||||
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
return Diag(Loc, diag::err_undeclared_var_use, II.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D)) {
|
|
||||||
// For ParmVarDecl's, we perform the default function/array conversion
|
|
||||||
// (C99 6.7.5.3p[7,8]).
|
|
||||||
QualType DeclRefType;
|
|
||||||
if (const ArrayType *AT = PD->getType()->getAsArrayType())
|
|
||||||
DeclRefType = Context.getPointerType(AT->getElementType());
|
|
||||||
else if (PD->getType()->isFunctionType())
|
|
||||||
DeclRefType = Context.getPointerType(PD->getType());
|
|
||||||
else
|
|
||||||
DeclRefType = PD->getType();
|
|
||||||
return new DeclRefExpr(PD, DeclRefType, Loc);
|
|
||||||
}
|
|
||||||
// The function/arrray conversion cannot be done for ValueDecl's in general.
|
|
||||||
// Consider this example:
|
|
||||||
//
|
|
||||||
// void func(int parmvardecl[5]) {
|
|
||||||
// int blockvardecl[5];
|
|
||||||
// sizeof(parmvardecl); // type is "int *" (converted from "int [5]")
|
|
||||||
// sizeof(blockvardecl); // type is "int [5]" (cannot convert to "int *")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If we converted blockvardecl (at this level) it would be be incorrect
|
|
||||||
// for the sizeof and address of (&) operators (see C99 6.3.2.1p[2-4]).
|
|
||||||
// This doesn't matter for parmvardecl, since arrays are always passed by
|
|
||||||
// reference (i.e. the [5] on parmvardecl is superfluous).
|
|
||||||
//
|
|
||||||
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
|
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
|
||||||
return new DeclRefExpr(VD, VD->getType(), Loc);
|
return new DeclRefExpr(VD, VD->getType(), Loc);
|
||||||
if (isa<TypedefDecl>(D))
|
if (isa<TypedefDecl>(D))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue