diff options
author | Chris Lattner <sabre@nondot.org> | 2009-04-25 06:12:16 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-04-25 06:12:16 +0000 |
commit | 2dbd285f5033ca6dea25babfd1c43d9fec35e7e5 (patch) | |
tree | e3a1f6f14316cf44f45dcc28f142ca4db08487b3 /lib/Sema/SemaDecl.cpp | |
parent | 1ad9b28e3217c2349a04f3d3bf14f9c73a99afa7 (diff) |
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’
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70016 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8dd4356046..9930dbc19b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2122,15 +2122,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, 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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, 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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, 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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // @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 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, 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 |