[cfe-commits] r70016 - in /cfe/trunk: lib/AST/Decl.cpp lib/Sema/SemaDecl.cpp test/Sema/function.c

Chris Lattner sabre at nondot.org
Fri Apr 24 23:12:16 PDT 2009


Author: lattner
Date: Sat Apr 25 01:12:16 2009
New Revision: 70016

URL: http://llvm.org/viewvc/llvm-project?rev=70016&view=rev
Log:
fix PR4049, a crash on invalid, by making sema install the right number of 
parameters in a functiondecl, even if the decl is invalid and has a confusing
Declarator.  On the testcase, we now emit one beautiful diagnostic:

t.c:2:1: error: unknown type name 'unknown_type'
unknown_type f(void*)
^

GCC 4.0 produces:

t.c:2: error: syntax error before ‘f’
t.c: In function ‘f’:
t.c:2: error: parameter name omitted

and GCC 4.2:

t.c:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘f’


Modified:
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/function.c

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=70016&r1=70015&r2=70016&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sat Apr 25 01:12:16 2009
@@ -432,7 +432,7 @@
 
 
 /// getNumParams - Return the number of parameters this function must have
-/// based on its functiontype.  This is the length of the PararmInfo array
+/// based on its FunctionType.  This is the length of the PararmInfo array
 /// after it has been created.
 unsigned FunctionDecl::getNumParams() const {
   const FunctionType *FT = getType()->getAsFunctionType();
@@ -445,8 +445,7 @@
 void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
                              unsigned NumParams) {
   assert(ParamInfo == 0 && "Already has param info!");
-  assert(NumParams == getNumParams() &&
-         "Parameter count mismatch!");
+  assert(NumParams == getNumParams() && "Parameter count mismatch!");
   
   // Zero params -> null pointer.
   if (NumParams) {

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=70016&r1=70015&r2=70016&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 25 01:12:16 2009
@@ -2122,15 +2122,12 @@
                                                         SE->getByteLength())));
   }
 
-  // Copy the parameter declarations from the declarator D to
-  // the function declaration NewFD, if they are available.
+  // Copy the parameter declarations from the declarator D to the function
+  // declaration NewFD, if they are available.  First scavenge them into Params.
+  llvm::SmallVector<ParmVarDecl*, 16> Params;
   if (D.getNumTypeObjects() > 0) {
     DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
 
-    // Create Decl objects for each parameter, adding them to the
-    // FunctionDecl.
-    llvm::SmallVector<ParmVarDecl*, 16> Params;
-  
     // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs
     // function that takes no arguments, not a function that takes a
     // single void argument.
@@ -2139,7 +2136,7 @@
     if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
         FTI.ArgInfo[0].Param &&
         FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType()) {
-      // empty arg list, don't push any params.
+      // Empty arg list, don't push any params.
       ParmVarDecl *Param = FTI.ArgInfo[0].Param.getAs<ParmVarDecl>();
 
       // In C++, the empty parameter-type-list must be spelled "void"; a
@@ -2147,12 +2144,12 @@
       if (getLangOptions().CPlusPlus &&
           Param->getType().getUnqualifiedType() != Context.VoidTy)
         Diag(Param->getLocation(), diag::err_param_typedef_of_void);
+      // FIXME: Leaks decl?
     } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
       for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
         Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>());
     }
   
-    NewFD->setParams(Context, &Params[0], Params.size());
   } else if (const FunctionProtoType *FT = R->getAsFunctionProtoType()) {
     // When we're declaring a function with a typedef, typeof, etc as in the
     // following example, we'll need to synthesize (unnamed)
@@ -2164,7 +2161,6 @@
     // @endcode
     
     // Synthesize a parameter for each argument type.
-    llvm::SmallVector<ParmVarDecl*, 16> Params;
     for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
          AE = FT->arg_type_end(); AI != AE; ++AI) {
       ParmVarDecl *Param = ParmVarDecl::Create(Context, DC,
@@ -2173,9 +2169,31 @@
       Param->setImplicit();
       Params.push_back(Param);
     }
-
-    NewFD->setParams(Context, &Params[0], Params.size());
   }
+  
+  // If NewFD is invalid, then the Params list may not have the right number of
+  // decls for this FunctionDecl.  Because we want the AST to be as correct as
+  // possible, "fix" these problems by removing or adding params as needed.
+  if (NewFD->isInvalidDecl()) {
+    unsigned NumNeededParams = NewFD->getNumParams();
+    while (NumNeededParams > Params.size()) {
+      ParmVarDecl *Param = ParmVarDecl::Create(Context, DC,
+                                               SourceLocation(), 0,
+                                               Context.IntTy, VarDecl::None, 0);
+      Param->setImplicit();
+      Param->setInvalidDecl();
+      Params.push_back(Param);
+    }
+    
+    while (NumNeededParams < Params.size()) {
+      Params.pop_back();
+      // FIXME: Don't leak the decl.
+    }
+  }
+  
+  // Finally, we know we have the right number of parameters, install them.
+  NewFD->setParams(Context, &Params[0], Params.size());
+  
     
   // If name lookup finds a previous declaration that is not in the
   // same scope as the new declaration, this may still be an

Modified: cfe/trunk/test/Sema/function.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/function.c?rev=70016&r1=70015&r2=70016&view=diff

==============================================================================
--- cfe/trunk/test/Sema/function.c (original)
+++ cfe/trunk/test/Sema/function.c Sat Apr 25 01:12:16 2009
@@ -79,4 +79,7 @@
 typedef void fn_t(void);
 fn_t t17;
 
+// PR4049
+unknown_type t18(void*) {   // expected-error {{unknown type name 'unknown_type'}}
+}
 





More information about the cfe-commits mailing list