aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2008-10-24 18:09:54 +0000
committerDouglas Gregor <dgregor@apple.com>2008-10-24 18:09:54 +0000
commit6cbd3df095ab92e0637265e88fe9c093135cdb03 (patch)
treece75f228570956be17d6177846a8ddbe0c860a6e
parent69bd3754b532de8dbb03449c12a74cc525697ef2 (diff)
PR2942: FunctionDecls by typedef crash the C++ front-end
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58100 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDecl.cpp31
-rw-r--r--test/SemaCXX/fntype-decl.cpp5
2 files changed, 35 insertions, 1 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index df4ade090e..4c36b09af8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -781,13 +781,42 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl) {
Param->getType().getUnqualifiedType() != Context.VoidTy) {
Diag(Param->getLocation(), diag::ext_param_typedef_of_void);
}
-
} else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) {
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i)
Params.push_back((ParmVarDecl *)FTI.ArgInfo[i].Param);
}
NewFD->setParams(&Params[0], Params.size());
+ } else if (R->getAsTypedefType()) {
+ // When we're declaring a function with a typedef, as in the
+ // following example, we'll need to synthesize (unnamed)
+ // parameters for use in the declaration.
+ //
+ // @code
+ // typedef void fn(int);
+ // fn f;
+ // @endcode
+ const FunctionTypeProto *FT = R->getAsFunctionTypeProto();
+ if (!FT) {
+ // This is a typedef of a function with no prototype, so we
+ // don't need to do anything.
+ } else if ((FT->getNumArgs() == 0) ||
+ (FT->getNumArgs() == 1 && !FT->isVariadic() &&
+ FT->getArgType(0)->isVoidType())) {
+ // This is a zero-argument function. We don't need to do anything.
+ } else {
+ // Synthesize a parameter for each argument type.
+ llvm::SmallVector<ParmVarDecl*, 16> Params;
+ for (FunctionTypeProto::arg_type_iterator ArgType = FT->arg_type_begin();
+ ArgType != FT->arg_type_end(); ++ArgType) {
+ Params.push_back(ParmVarDecl::Create(Context, CurContext,
+ SourceLocation(), 0,
+ *ArgType, VarDecl::None,
+ 0, 0));
+ }
+
+ NewFD->setParams(&Params[0], Params.size());
+ }
}
// Merge the decl with the existing one if appropriate. Since C functions
diff --git a/test/SemaCXX/fntype-decl.cpp b/test/SemaCXX/fntype-decl.cpp
new file mode 100644
index 0000000000..b54346624c
--- /dev/null
+++ b/test/SemaCXX/fntype-decl.cpp
@@ -0,0 +1,5 @@
+// RUN: clang -fsyntax-only -verify %s
+
+// PR2942
+typedef void fn(int);
+fn f;