diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/StmtDumper.cpp | 7 | ||||
-rw-r--r-- | lib/Basic/Diagnostic.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 5 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 26 | ||||
-rw-r--r-- | lib/Driver/Tools.cpp | 11 | ||||
-rw-r--r-- | lib/Frontend/CompilerInvocation.cpp | 15 | ||||
-rw-r--r-- | lib/Frontend/TextDiagnosticPrinter.cpp | 82 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 |
15 files changed, 179 insertions, 55 deletions
diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index ca62ed1..a11e313 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -260,6 +260,13 @@ void StmtDumper::DumpDeclarator(Decl *D) { else ns = "<anonymous>"; OS << '"' << UD->getDeclKindName() << ns << ";\""; + } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { + // print using decl (e.g. "using std::string;") + const char *tn = UD->isTypeName() ? "typename " : ""; + OS << '"' << UD->getDeclKindName() << tn; + UD->getTargetNestedNameDecl()->print(OS, + PrintingPolicy(UD->getASTContext().getLangOptions())); + OS << ";\""; } else { assert(0 && "Unexpected decl"); } diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 1870195..9e6f168 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -51,6 +51,8 @@ struct StaticDiagInfoRec { unsigned Mapping : 3; unsigned Class : 3; bool SFINAE : 1; + unsigned Category : 5; + const char *Description; const char *OptionGroup; @@ -63,8 +65,8 @@ struct StaticDiagInfoRec { }; static const StaticDiagInfoRec StaticDiagInfo[] = { -#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) \ - { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, DESC, GROUP }, +#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP,SFINAE, CATEGORY) \ + { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, CATEGORY, DESC, GROUP }, #include "clang/Basic/DiagnosticCommonKinds.inc" #include "clang/Basic/DiagnosticDriverKinds.inc" #include "clang/Basic/DiagnosticFrontendKinds.inc" @@ -73,7 +75,7 @@ static const StaticDiagInfoRec StaticDiagInfo[] = { #include "clang/Basic/DiagnosticASTKinds.inc" #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" - { 0, 0, 0, 0, 0, 0} + { 0, 0, 0, 0, 0, 0, 0} }; #undef DIAG @@ -99,7 +101,7 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { #endif // Search the diagnostic table with a binary search. - StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0 }; + StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0, 0, 0 }; const StaticDiagInfoRec *Found = std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index db24def..8082b33 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -532,6 +532,8 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { V = Builder.CreateBitCast(V, PtrStructTy); V = Builder.CreateStructGEP(V, getByRefValueLLVMField(VD), VD->getNameAsString()); + if (VD->getType()->isReferenceType()) + V = Builder.CreateLoad(V); } else { const llvm::Type *Ty = CGM.getTypes().ConvertType(VD->getType()); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 4963e73..48ae511 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -495,7 +495,10 @@ CollectRecordFields(const RecordDecl *RD, llvm::DIFile Unit, llvm::DIType CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method, llvm::DIFile Unit) { - llvm::DIType FnTy = getOrCreateType(Method->getType(), Unit); + llvm::DIType FnTy + = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(), + 0), + Unit); // Static methods do not need "this" pointer argument. if (Method->isStatic()) diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index ba3a2b4..48198ff 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -231,9 +231,6 @@ CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D, void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage) { - // Bail out early if the block is unreachable. - if (!Builder.GetInsertBlock()) return; - llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); @@ -245,9 +242,9 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, if (getContext().getLangOptions().CPlusPlus) CGM.setStaticLocalDeclAddress(&D, GV); + // We can't have a VLA here, but we can have a pointer to a VLA, + // even though that doesn't really make any sense. // Make sure to evaluate VLA bounds now so that we have them for later. - // - // FIXME: Can this happen? if (D.getType()->isVariablyModifiedType()) EmitVLASize(D.getType()); diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index f6c805f..6afa538 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -279,6 +279,9 @@ static llvm::Constant *getGuardAbortFn(CodeGenFunction &CGF) { void CodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV) { + // Bail out early if this initializer isn't reachable. + if (!Builder.GetInsertBlock()) return; + bool ThreadsafeStatics = getContext().getLangOptions().ThreadsafeStatics; llvm::SmallString<256> GuardVName; diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 3359250..8426f71 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -441,18 +441,20 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, LoadObjCSelf(), Ivar, 0); const RecordType *RT = FieldType->getAs<RecordType>(); CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); - if (Array) { - const llvm::Type *BasePtr = ConvertType(FieldType); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(LV.getAddress(), BasePtr); - EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), - Array, BaseAddrPtr); - } - else - EmitCXXDestructorCall(FieldClassDecl->getDestructor(CGM.getContext()), - Dtor_Complete, /*ForVirtualBase=*/false, - LV.getAddress()); + CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(getContext()); + if (!Dtor->isTrivial()) + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LV.getAddress(), BasePtr); + EmitCXXAggrDestructorCall(Dtor, + Array, BaseAddrPtr); + } + else + EmitCXXDestructorCall(Dtor, + Dtor_Complete, /*ForVirtualBase=*/false, + LV.getAddress()); } } FinishFunction(); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 176d491..5a3916d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -21,6 +21,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/Util.h" +#include "clang/Frontend/DiagnosticOptions.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" @@ -1082,11 +1083,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else CmdArgs.push_back("19"); + CmdArgs.push_back("-fmacro-backtrace-limit"); + if (Arg *A = Args.getLastArg(options::OPT_fmacro_backtrace_limit_EQ)) + CmdArgs.push_back(A->getValue(Args)); + else + CmdArgs.push_back(Args.MakeArgString( + llvm::Twine(DiagnosticOptions::DefaultMacroBacktraceLimit))); + CmdArgs.push_back("-ftemplate-backtrace-limit"); if (Arg *A = Args.getLastArg(options::OPT_ftemplate_backtrace_limit_EQ)) CmdArgs.push_back(A->getValue(Args)); else - CmdArgs.push_back("10"); + CmdArgs.push_back(Args.MakeArgString( + llvm::Twine(DiagnosticOptions::DefaultTemplateBacktraceLimit))); // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8ffdde2..729c1dc 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -247,7 +247,13 @@ static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts, Res.push_back("-ferror-limit"); Res.push_back(llvm::utostr(Opts.ErrorLimit)); } - if (Opts.TemplateBacktraceLimit != 10) { + if (Opts.MacroBacktraceLimit + != DiagnosticOptions::DefaultMacroBacktraceLimit) { + Res.push_back("-fmacro-backtrace-limit"); + Res.push_back(llvm::utostr(Opts.MacroBacktraceLimit)); + } + if (Opts.TemplateBacktraceLimit + != DiagnosticOptions::DefaultTemplateBacktraceLimit) { Res.push_back("-ftemplate-backtrace-limit"); Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit)); } @@ -877,8 +883,13 @@ static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary); Opts.ErrorLimit = getLastArgIntValue(Args, OPT_ferror_limit, 0, Diags); + Opts.MacroBacktraceLimit + = getLastArgIntValue(Args, OPT_fmacro_backtrace_limit, + DiagnosticOptions::DefaultMacroBacktraceLimit, Diags); Opts.TemplateBacktraceLimit - = getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, 0, Diags); + = getLastArgIntValue(Args, OPT_ftemplate_backtrace_limit, + DiagnosticOptions::DefaultTemplateBacktraceLimit, + Diags); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 28bb17a..66ed956 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -285,7 +285,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, const SourceManager &SM, const FixItHint *Hints, unsigned NumHints, - unsigned Columns) { + unsigned Columns, + unsigned OnMacroInst, + unsigned MacroSkipStart, + unsigned MacroSkipEnd) { assert(LangOpts && "Unexpected diagnostic outside source file processing"); assert(!Loc.isInvalid() && "must have a valid source location here"); @@ -293,10 +296,16 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, // instantiated (recursively) then emit information about where the token was // spelled from. if (!Loc.isFileID()) { + // Whether to suppress printing this macro instantiation. + bool Suppressed + = OnMacroInst >= MacroSkipStart && OnMacroInst < MacroSkipEnd; + + SourceLocation OneLevelUp = SM.getImmediateInstantiationRange(Loc).first; // FIXME: Map ranges? - EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns); - + EmitCaretDiagnostic(OneLevelUp, Ranges, NumRanges, SM, 0, 0, Columns, + OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); + // Map the location. Loc = SM.getImmediateSpellingLoc(Loc); @@ -308,26 +317,38 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, Ranges[i] = SourceRange(S, E); } - // Get the pretty name, according to #line directives etc. - PresumedLoc PLoc = SM.getPresumedLoc(Loc); + if (!Suppressed) { + // Get the pretty name, according to #line directives etc. + PresumedLoc PLoc = SM.getPresumedLoc(Loc); - // If this diagnostic is not in the main file, print out the "included from" - // lines. - if (LastWarningLoc != PLoc.getIncludeLoc()) { - LastWarningLoc = PLoc.getIncludeLoc(); - PrintIncludeStack(LastWarningLoc, SM); - } + // If this diagnostic is not in the main file, print out the + // "included from" lines. + if (LastWarningLoc != PLoc.getIncludeLoc()) { + LastWarningLoc = PLoc.getIncludeLoc(); + PrintIncludeStack(LastWarningLoc, SM); + } - if (DiagOpts->ShowLocation) { - // Emit the file/line/column that this expansion came from. - OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'; - if (DiagOpts->ShowColumn) - OS << PLoc.getColumn() << ':'; - OS << ' '; + if (DiagOpts->ShowLocation) { + // Emit the file/line/column that this expansion came from. + OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'; + if (DiagOpts->ShowColumn) + OS << PLoc.getColumn() << ':'; + OS << ' '; + } + OS << "note: instantiated from:\n"; + + EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns, + OnMacroInst + 1, MacroSkipStart, MacroSkipEnd); + return; } - OS << "note: instantiated from:\n"; - - EmitCaretDiagnostic(Loc, Ranges, NumRanges, SM, Hints, NumHints, Columns); + + if (OnMacroInst == MacroSkipStart) { + // Tell the user that we've skipped contexts. + OS << "note: (skipping " << (MacroSkipEnd - MacroSkipStart) + << " contexts in backtrace; use -fmacro-backtrace-limit=0 to see " + "all)\n"; + } + return; } @@ -866,10 +887,29 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, } } + unsigned MacroInstSkipStart = 0, MacroInstSkipEnd = 0; + if (DiagOpts && DiagOpts->MacroBacktraceLimit && !LastLoc.isFileID()) { + // Compute the length of the macro-instantiation backtrace, so that we + // can establish which steps in the macro backtrace we'll skip. + SourceLocation Loc = LastLoc; + unsigned Depth = 0; + do { + ++Depth; + Loc = LastLoc.getManager().getImmediateInstantiationRange(Loc).first; + } while (!Loc.isFileID()); + + if (Depth > DiagOpts->MacroBacktraceLimit) { + MacroInstSkipStart = DiagOpts->MacroBacktraceLimit / 2 + + DiagOpts->MacroBacktraceLimit % 2; + MacroInstSkipEnd = Depth - DiagOpts->MacroBacktraceLimit / 2; + } + } + EmitCaretDiagnostic(LastLoc, Ranges, NumRanges, LastLoc.getManager(), Info.getFixItHints(), Info.getNumFixItHints(), - DiagOpts->MessageLength); + DiagOpts->MessageLength, + 0, MacroInstSkipStart, MacroInstSkipEnd); } OS.flush(); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0e839a9..a802679 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3243,8 +3243,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), AE = FT->arg_type_end(); AI != AE; ++AI) { ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD, - SourceLocation(), 0, - *AI, /*TInfo=*/0, + D.getIdentifierLoc(), 0, + *AI, + Context.getTrivialTypeSourceInfo(*AI, + D.getIdentifierLoc()), VarDecl::None, VarDecl::None, 0); Param->setImplicit(); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6259b85a..b9c7d79 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4134,13 +4134,16 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, /// /// \param From The expression we are copying from. /// +/// \param CopyingBaseSubobject Whether we're copying a base subobject. +/// Otherwise, it's a non-static member subobject. +/// /// \param Depth Internal parameter recording the depth of the recursion. /// /// \returns A statement or a loop that copies the expressions. static Sema::OwningStmtResult BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, Sema::OwningExprResult To, Sema::OwningExprResult From, - unsigned Depth = 0) { + bool CopyingBaseSubobject, unsigned Depth = 0) { typedef Sema::OwningStmtResult OwningStmtResult; typedef Sema::OwningExprResult OwningExprResult; @@ -4172,6 +4175,25 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, } F.done(); + // Suppress the protected check (C++ [class.protected]) for each of the + // assignment operators we found. This strange dance is required when + // we're assigning via a base classes's copy-assignment operator. To + // ensure that we're getting the right base class subobject (without + // ambiguities), we need to cast "this" to that subobject type; to + // ensure that we don't go through the virtual call mechanism, we need + // to qualify the operator= name with the base class (see below). However, + // this means that if the base class has a protected copy assignment + // operator, the protected member access check will fail. So, we + // rewrite "protected" access to "public" access in this case, since we + // know by construction that we're calling from a derived class. + if (CopyingBaseSubobject) { + for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end(); + L != LEnd; ++L) { + if (L.getAccess() == AS_protected) + L.setAccess(AS_public); + } + } + // Create the nested-name-specifier that will be used to qualify the // reference to operator=; this is required to suppress the virtual // call mechanism. @@ -4277,7 +4299,8 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, // Build the copy for an individual element of the array. OwningStmtResult Copy = BuildSingleCopyAssign(S, Loc, ArrayTy->getElementType(), - move(To), move(From), Depth+1); + move(To), move(From), + CopyingBaseSubobject, Depth+1); if (Copy.isInvalid()) { InitStmt->Destroy(S.Context); return S.StmtError(); @@ -4381,7 +4404,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Build the copy. OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, BaseType, - move(To), Owned(From)); + move(To), Owned(From), + /*CopyingBaseSubobject=*/true); if (Copy.isInvalid()) { Invalid = true; continue; @@ -4501,7 +4525,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Build the copy of this field. OwningStmtResult Copy = BuildSingleCopyAssign(*this, Loc, FieldType, - move(To), move(From)); + move(To), move(From), + /*CopyingBaseSubobject=*/false); if (Copy.isInvalid()) { Invalid = true; continue; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c4ab03f..869d6df 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3565,8 +3565,8 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) { if (BO->getOpcode() == BinaryOperator::PtrMemD || BO->getOpcode() == BinaryOperator::PtrMemI) { - if (const FunctionProtoType *FPT = - dyn_cast<FunctionProtoType>(BO->getType())) { + if (const FunctionProtoType *FPT + = BO->getType()->getAs<FunctionProtoType>()) { QualType ResultTy = FPT->getResultType().getNonReferenceType(); ExprOwningPtr<CXXMemberCallExpr> diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 21f2a51..b87fa7d 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -6513,7 +6513,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemExpr->setBase(ObjectArg); // Convert the rest of the arguments - const FunctionProtoType *Proto = cast<FunctionProtoType>(Method->getType()); + const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); if (ConvertArgumentsForCall(&*TheCall, MemExpr, Method, Proto, Args, NumArgs, RParenLoc)) return ExprError(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8b851b2..da84806 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1169,6 +1169,27 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return 0; QualType T = TInfo->getType(); + // \brief If the type of this function is not *directly* a function + // type, then we're instantiating the a function that was declared + // via a typedef, e.g., + // + // typedef int functype(int, int); + // functype func; + // + // In this case, we'll just go instantiate the ParmVarDecls that we + // synthesized in the method declaration. + if (!isa<FunctionProtoType>(T)) { + assert(!Params.size() && "Instantiating type could not yield parameters"); + for (unsigned I = 0, N = D->getNumParams(); I != N; ++I) { + ParmVarDecl *P = SemaRef.SubstParmVarDecl(D->getParamDecl(I), + TemplateArgs); + if (!P) + return 0; + + Params.push_back(P); + } + } + NestedNameSpecifier *Qualifier = D->getQualifier(); if (Qualifier) { Qualifier = SemaRef.SubstNestedNameSpecifier(Qualifier, |