]> granicus.if.org Git - clang/commitdiff
Make sure the good old "function/array conversion" is done to function parameters.
authorSteve Naroff <snaroff@apple.com>
Sun, 5 Aug 2007 02:16:31 +0000 (02:16 +0000)
committerSteve Naroff <snaroff@apple.com>
Sun, 5 Aug 2007 02:16:31 +0000 (02:16 +0000)
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

Sema/SemaExpr.cpp
include/clang/AST/Decl.h
test/Parser/parmvardecl_conversion.c [new file with mode: 0644]

index 9dfcd7d5eab08f760f71402a6c25b0368e9b1fb0..bfa6f882b5585174888bf1a226f8f19d88b5a3d6 100644 (file)
@@ -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<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) 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<ValueDecl>(D))
     return new DeclRefExpr(VD, VD->getType(), Loc);
   if (isa<TypedefDecl>(D))
index a67762a6746deeba5c755e8fb4f0adb9fde11b18..90af50c36fa1ae468510ca23e7826752fabefc9d 100644 (file)
@@ -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 (file)
index 0000000..5fb9528
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: clang -parse-ast-check %s
+
+void f (int p[]) { p++; }
+