From: Steve Naroff Date: Sun, 5 Aug 2007 02:16:31 +0000 (+0000) Subject: Make sure the good old "function/array conversion" is done to function parameters. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69625f4925646669f68caa234cd9133261acaaa1;p=clang Make sure the good old "function/array conversion" is done to function parameters. This resulted in the following error... [dylan:clang/test/Parser] admin% cat parmvardecl_conversion.c // RUN: clang -parse-ast-check %s void f (int p[]) { p++; } [dylan:clang/test/Parser] admin% clang -parse-ast-check parmvardecl_conversion.c Errors seen but not expected: Line 3: cannot modify value of type 'int []' With this fix, the test case above succeeds. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40831 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index 9dfcd7d5ea..bfa6f882b5 100644 --- a/Sema/SemaExpr.cpp +++ b/Sema/SemaExpr.cpp @@ -73,7 +73,32 @@ Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc, return Diag(Loc, diag::err_undeclared_var_use, II.getName()); } } - + if (ParmVarDecl *PD = dyn_cast(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) is 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(D)) return new DeclRefExpr(VD, VD->getType(), Loc); if (isa(D)) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a67762a674..90af50c36f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -198,7 +198,7 @@ public: ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, Decl *PrevDecl) : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {} - + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == ParmVariable; } static bool classof(const ParmVarDecl *D) { return true; } diff --git a/test/Parser/parmvardecl_conversion.c b/test/Parser/parmvardecl_conversion.c new file mode 100644 index 0000000000..5fb95280ff --- /dev/null +++ b/test/Parser/parmvardecl_conversion.c @@ -0,0 +1,4 @@ +// RUN: clang -parse-ast-check %s + +void f (int p[]) { p++; } +