[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