From 265c92560db8af7e64dc328cb612076086a62bd1 Mon Sep 17 00:00:00 2001 From: ed Date: Sat, 6 Jun 2009 08:21:31 +0000 Subject: Import clang, at r72995. --- lib/Sema/CMakeLists.txt | 1 + lib/Sema/Sema.h | 45 ++-- lib/Sema/SemaDecl.cpp | 73 +++++- lib/Sema/SemaDeclCXX.cpp | 2 +- lib/Sema/SemaDeclObjC.cpp | 33 +-- lib/Sema/SemaExprCXX.cpp | 26 +- lib/Sema/SemaTemplate.cpp | 192 +++++---------- lib/Sema/SemaTemplateDeduction.cpp | 395 +++++++++++++++++++++++++++++++ lib/Sema/SemaTemplateInstantiate.cpp | 34 ++- lib/Sema/SemaTemplateInstantiateExpr.cpp | 3 +- lib/Sema/SemaTemplateInstantiateStmt.cpp | 8 +- 11 files changed, 606 insertions(+), 206 deletions(-) create mode 100644 lib/Sema/SemaTemplateDeduction.cpp (limited to 'lib/Sema') diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index 321dac1..85c67df 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangSema SemaOverload.cpp SemaStmt.cpp SemaTemplate.cpp + SemaTemplateDeduction.cpp SemaTemplateInstantiate.cpp SemaTemplateInstantiateDecl.cpp SemaTemplateInstantiateExpr.cpp diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index c428d29..d3bfef6 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -20,6 +20,7 @@ #include "SemaOverload.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Parse/Action.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallVector.h" @@ -471,6 +472,7 @@ public: Declarator *D = 0); virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, + DeclPtrTy IntfDecl, Declarator &D, ExprTy *BitfieldWidth, tok::ObjCKeywordKind visibility); @@ -1045,7 +1047,7 @@ public: LookupResult LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly = false, - bool AllowBuiltinCreation = true, + bool AllowBuiltinCreation = false, SourceLocation Loc = SourceLocation()); LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, LookupNameKind NameKind, @@ -1054,7 +1056,7 @@ public: DeclarationName Name, LookupNameKind NameKind, bool RedeclarationOnly = false, - bool AllowBuiltinCreation = true, + bool AllowBuiltinCreation = false, SourceLocation Loc = SourceLocation()); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II); @@ -1629,6 +1631,12 @@ public: TypeTy *Ty, SourceLocation RParen); + /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is + /// non-empty, will create a new CXXExprWithTemporaries expression. + /// Otherwise, just returs the passed in expression. + Expr *MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, + bool DestroyTemps = true); + virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr); bool RequireCompleteDeclContext(const CXXScopeSpec &SS); @@ -1971,7 +1979,7 @@ public: const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, - llvm::SmallVectorImpl &Converted); + TemplateArgumentListBuilder &Converted); bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg, SourceLocation ArgLoc); @@ -1980,7 +1988,7 @@ public: bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member); bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, - llvm::SmallVectorImpl *Converted = 0); + TemplateArgumentListBuilder *Converted = 0); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg); bool TemplateParameterListsAreEqual(TemplateParameterList *New, TemplateParameterList *Old, @@ -2019,16 +2027,9 @@ public: const IdentifierInfo &II, SourceRange Range); - bool DeduceTemplateArguments(QualType Param, QualType Arg, - llvm::SmallVectorImpl &Deduced); - bool DeduceTemplateArguments(const TemplateArgument &Param, - const TemplateArgument &Arg, - llvm::SmallVectorImpl &Deduced); - bool DeduceTemplateArguments(const TemplateArgumentList &ParamList, - const TemplateArgumentList &ArgList, - llvm::SmallVectorImpl &Deduced); - bool DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs); + TemplateArgumentList * + DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs); //===--------------------------------------------------------------------===// // C++ Template Instantiation @@ -2235,7 +2236,7 @@ public: QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity); - + OwningExprResult InstantiateExpr(Expr *E, const TemplateArgumentList &TemplateArgs); @@ -2456,7 +2457,19 @@ public: SourceLocation PragmaLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); - + + /// ActOnPragmaWeakID - Called on well formed #pragma weak ident. + virtual void ActOnPragmaWeakID(IdentifierInfo* WeakName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc); + + /// ActOnPragmaWeakAlias - Called on well formed #pragma weak ident = ident. + virtual void ActOnPragmaWeakAlias(IdentifierInfo* WeakName, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation WeakNameLoc, + SourceLocation AliasNameLoc); + /// getPragmaPackAlignment() - Return the current alignment as specified by /// the current #pragma pack directive, or 0 if none is currently active. unsigned getPragmaPackAlignment() const; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 959154c..c67af29 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -575,10 +575,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { // If we have a redefinition of a typedef in C, emit a warning. This warning // is normally mapped to an error, but can be controlled with - // -Wtypedef-redefinition. If either the original was in a system header, - // don't emit this for compatibility with GCC. + // -Wtypedef-redefinition. If either the original or the redefinition is + // in a system header, don't emit this for compatibility with GCC. if (PP.getDiagnostics().getSuppressSystemWarnings() && - Context.getSourceManager().isInSystemHeader(Old->getLocation())) + (Context.getSourceManager().isInSystemHeader(Old->getLocation()) || + Context.getSourceManager().isInSystemHeader(New->getLocation()))) return; Diag(New->getLocation(), diag::warn_redefinition_of_typedef) @@ -3913,6 +3914,7 @@ TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { /// in order to create an IvarDecl object for it. Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, SourceLocation DeclStart, + DeclPtrTy IntfDecl, Declarator &D, ExprTy *BitfieldWidth, tok::ObjCKeywordKind Visibility) { @@ -3951,14 +3953,28 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword ? TranslateIvarVisibility(Visibility) : ObjCIvarDecl::None; - + // Must set ivar's DeclContext to its enclosing interface. + Decl *EnclosingDecl = IntfDecl.getAs(); + DeclContext *EnclosingContext; + if (ObjCImplementationDecl *IMPDecl = + dyn_cast(EnclosingDecl)) { + // Case of ivar declared in an implementation. Context is that of its class. + ObjCInterfaceDecl* IDecl = IMPDecl->getClassInterface(); + assert(IDecl && "No class- ActOnIvar"); + EnclosingContext = cast_or_null(IDecl); + } + else + EnclosingContext = dyn_cast(EnclosingDecl); + assert(EnclosingContext && "null DeclContext for ivar - ActOnIvar"); + // Construct the decl. - ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, CurContext, Loc, II, T,ac, + ObjCIvarDecl *NewID = ObjCIvarDecl::Create(Context, + EnclosingContext, Loc, II, T,ac, (Expr *)BitfieldWidth); if (II) { NamedDecl *PrevDecl = LookupName(S, II, LookupMemberName, true); - if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S) + if (PrevDecl && isDeclInScope(PrevDecl, EnclosingContext, S) && !isa(PrevDecl)) { Diag(Loc, diag::err_duplicate_member) << II; Diag(PrevDecl->getLocation(), diag::note_previous_declaration); @@ -4099,7 +4115,11 @@ void Sema::ActOnFields(Scope* S, if (ObjCInterfaceDecl *ID = dyn_cast(EnclosingDecl)) { ID->setIVarList(ClsFields, RecFields.size(), Context); ID->setLocEnd(RBrac); - + // Add ivar's to class's DeclContext. + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + ClsFields[i]->setLexicalDeclContext(ID); + ID->addDecl(Context, ClsFields[i]); + } // Must enforce the rule that ivars in the base classes may not be // duplicates. if (ID->getSuperClass()) { @@ -4120,12 +4140,10 @@ void Sema::ActOnFields(Scope* S, } else if (ObjCImplementationDecl *IMPDecl = dyn_cast(EnclosingDecl)) { assert(IMPDecl && "ActOnFields - missing ObjCImplementationDecl"); - for (unsigned I = 0, N = RecFields.size(); I != N; ++I) { - // FIXME: Set the DeclContext correctly when we build the - // declarations. + for (unsigned I = 0, N = RecFields.size(); I != N; ++I) + // Ivar declared in @implementation never belongs to the implementation. + // Only it is in implementation's lexical context. ClsFields[I]->setLexicalDeclContext(IMPDecl); - IMPDecl->addDecl(Context, ClsFields[I]); - } CheckImplementationIvars(IMPDecl, ClsFields, RecFields.size(), RBrac); } } @@ -4413,3 +4431,34 @@ Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, CurContext->addDecl(Context, New); return DeclPtrTy::make(New); } + +void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, + SourceLocation PragmaLoc, + SourceLocation NameLoc) { + Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName); + + // FIXME: This implementation is an ugly hack! + if (PrevDecl) { + PrevDecl->addAttr(::new (Context) WeakAttr()); + return; + } + Diag(PragmaLoc, diag::err_unsupported_pragma_weak); + return; +} + +void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, + IdentifierInfo* AliasName, + SourceLocation PragmaLoc, + SourceLocation NameLoc, + SourceLocation AliasNameLoc) { + Decl *PrevDecl = LookupName(TUScope, Name, LookupOrdinaryName); + + // FIXME: This implementation is an ugly hack! + if (PrevDecl) { + PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName())); + PrevDecl->addAttr(::new (Context) WeakAttr()); + return; + } + Diag(PragmaLoc, diag::err_unsupported_pragma_weak); + return; +} diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f13179f..b59ac87 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1357,7 +1357,7 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { if (!Constructor->isInvalidDecl() && ((Constructor->getNumParams() == 1) || (Constructor->getNumParams() > 1 && - Constructor->getParamDecl(1)->getDefaultArg() != 0))) { + Constructor->getParamDecl(1)->hasDefaultArg()))) { QualType ParamType = Constructor->getParamDecl(0)->getType(); QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 8f58034..2500a8f 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2113,27 +2113,6 @@ bool Sema::CheckObjCDeclScope(Decl *D) { return true; } -/// Collect the instance variables declared in an Objective-C object. Used in -/// the creation of structures from objects using the @defs directive. -/// FIXME: This should be consolidated with CollectObjCIvars as it is also -/// part of the AST generation logic of @defs. -static void CollectIvars(ObjCInterfaceDecl *Class, RecordDecl *Record, - ASTContext& Ctx, - llvm::SmallVectorImpl &ivars) { - if (Class->getSuperClass()) - CollectIvars(Class->getSuperClass(), Record, Ctx, ivars); - - // For each ivar, create a fresh ObjCAtDefsFieldDecl. - for (ObjCInterfaceDecl::ivar_iterator I = Class->ivar_begin(), - E = Class->ivar_end(); I != E; ++I) { - ObjCIvarDecl* ID = *I; - Decl *FD = ObjCAtDefsFieldDecl::Create(Ctx, Record, ID->getLocation(), - ID->getIdentifier(), ID->getType(), - ID->getBitWidth()); - ivars.push_back(Sema::DeclPtrTy::make(FD)); - } -} - /// Called whenever @defs(ClassName) is encountered in the source. Inserts the /// instance variables of ClassName into Decls. void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, @@ -2151,7 +2130,17 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, } // Collect the instance variables - CollectIvars(Class, dyn_cast(TagD.getAs()), Context, Decls); + llvm::SmallVector RecFields; + Context.CollectObjCIvars(Class, RecFields); + // For each ivar, create a fresh ObjCAtDefsFieldDecl. + for (unsigned i = 0; i < RecFields.size(); i++) { + FieldDecl* ID = RecFields[i]; + RecordDecl *Record = dyn_cast(TagD.getAs()); + Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, ID->getLocation(), + ID->getIdentifier(), ID->getType(), + ID->getBitWidth()); + Decls.push_back(Sema::DeclPtrTy::make(FD)); + } // Introduce all of these fields into the appropriate scope. for (llvm::SmallVectorImpl::iterator D = Decls.begin(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 65018da..ed4ac55 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1588,16 +1588,26 @@ Expr *Sema::RemoveOutermostTemporaryBinding(Expr *E) { return E; } +Expr *Sema::MaybeCreateCXXExprWithTemporaries(Expr *SubExpr, + bool DestroyTemps) { + assert(SubExpr && "sub expression can't be null!"); + + if (ExprTemporaries.empty()) + return SubExpr; + + Expr *E = CXXExprWithTemporaries::Create(Context, SubExpr, + &ExprTemporaries[0], + ExprTemporaries.size(), + DestroyTemps); + ExprTemporaries.clear(); + + return E; +} + Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) { Expr *FullExpr = Arg.takeAs(); - - if (FullExpr && !ExprTemporaries.empty()) { - // Create a cleanup expr. - FullExpr = CXXExprWithTemporaries::Create(Context, FullExpr, - &ExprTemporaries[0], - ExprTemporaries.size()); - ExprTemporaries.clear(); - } + if (FullExpr) + FullExpr = MaybeCreateCXXExprWithTemporaries(FullExpr); return Owned(FullExpr); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 782a0d8..f9176ca 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -750,6 +750,10 @@ static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs, Canonical.reserve(NumTemplateArgs); for (unsigned Idx = 0; Idx < NumTemplateArgs; ++Idx) { switch (TemplateArgs[Idx].getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + break; + case TemplateArgument::Expression: // FIXME: Build canonical expression (!) Canonical.push_back(TemplateArgs[Idx]); @@ -765,11 +769,13 @@ static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs, Canonical.push_back(TemplateArgument(SourceLocation(), *TemplateArgs[Idx].getAsIntegral(), TemplateArgs[Idx].getIntegralType())); + break; case TemplateArgument::Type: { QualType CanonType = Context.getCanonicalType(TemplateArgs[Idx].getAsType()); Canonical.push_back(TemplateArgument(SourceLocation(), CanonType)); + break; } } } @@ -805,7 +811,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. - llvm::SmallVector ConvertedTemplateArgs; + TemplateArgumentListBuilder ConvertedTemplateArgs(Context); if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc, ConvertedTemplateArgs)) @@ -829,15 +835,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // template struct A; TemplateName CanonName = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType(CanonName, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); + ConvertedTemplateArgs.getFlatArgumentList(), + ConvertedTemplateArgs.flatSize()); } else if (ClassTemplateDecl *ClassTemplate = dyn_cast(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); + ClassTemplateSpecializationDecl::Profile(ID, + ConvertedTemplateArgs.getFlatArgumentList(), + ConvertedTemplateArgs.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *Decl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -846,12 +853,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // specialization. Create the canonical declaration and add it to // the set of specializations. Decl = ClassTemplateSpecializationDecl::Create(Context, - ClassTemplate->getDeclContext(), - TemplateLoc, - ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), - 0); + ClassTemplate->getDeclContext(), + TemplateLoc, + ClassTemplate, + ConvertedTemplateArgs, 0); ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); Decl->setLexicalDeclContext(CurContext); } @@ -949,7 +954,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, - llvm::SmallVectorImpl &Converted) { + TemplateArgumentListBuilder &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); unsigned NumArgs = NumTemplateArgs; @@ -998,13 +1003,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // on the previously-computed template arguments. if (ArgType->isDependentType()) { InstantiatingTemplate Inst(*this, TemplateLoc, - Template, &Converted[0], - Converted.size(), + Template, Converted.getFlatArgumentList(), + Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); - TemplateArgumentList TemplateArgs(Context, &Converted[0], - Converted.size(), - /*CopyArgs=*/false); + TemplateArgumentList TemplateArgs(Context, Converted, + /*CopyArgs=*/false, + /*FlattenArgs=*/false); ArgType = InstantiateType(ArgType, TemplateArgs, TTP->getDefaultArgumentLoc(), TTP->getDeclName()); @@ -1069,13 +1074,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (NTTPType->isDependentType()) { // Instantiate the type of the non-type template parameter. InstantiatingTemplate Inst(*this, TemplateLoc, - Template, &Converted[0], - Converted.size(), + Template, Converted.getFlatArgumentList(), + Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); - TemplateArgumentList TemplateArgs(Context, &Converted[0], - Converted.size(), - /*CopyArgs=*/false); + TemplateArgumentList TemplateArgs(Context, Converted, + /*CopyArgs=*/false, + /*FlattenArgs=*/false); NTTPType = InstantiateType(NTTPType, TemplateArgs, NTTP->getLocation(), NTTP->getDeclName()); @@ -1092,6 +1097,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, } switch (Arg.getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + break; + case TemplateArgument::Expression: { Expr *E = Arg.getAsExpr(); if (CheckTemplateArgument(NTTP, NTTPType, E, &Converted)) @@ -1131,6 +1140,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, = cast(*Param); switch (Arg.getKind()) { + case TemplateArgument::Null: + assert(false && "Should never see a NULL template argument here"); + break; + case TemplateArgument::Expression: { Expr *ArgExpr = Arg.getAsExpr(); if (ArgExpr && isa(ArgExpr) && @@ -1379,7 +1392,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { /// of this argument will be added to the end of the Converted vector. bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, - llvm::SmallVectorImpl *Converted) { + TemplateArgumentListBuilder *Converted) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); // If either the parameter has a dependent type or the argument is @@ -2051,7 +2064,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Check that the template argument list is well-formed for this // template. - llvm::SmallVector ConvertedTemplateArgs; + TemplateArgumentListBuilder ConvertedTemplateArgs(Context); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, &TemplateArgs[0], TemplateArgs.size(), RAngleLoc, ConvertedTemplateArgs)) @@ -2066,11 +2079,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, llvm::FoldingSetNodeID ID; if (isPartialSpecialization) // FIXME: Template parameter list matters, too - ClassTemplatePartialSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); + ClassTemplatePartialSpecializationDecl::Profile(ID, + ConvertedTemplateArgs.getFlatArgumentList(), + ConvertedTemplateArgs.flatSize()); else - ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); + ClassTemplateSpecializationDecl::Profile(ID, + ConvertedTemplateArgs.getFlatArgumentList(), + ConvertedTemplateArgs.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = 0; @@ -2111,12 +2126,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), - TemplateNameLoc, - TemplateParams, - ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), - PrevPartial); + TemplateNameLoc, + TemplateParams, + ClassTemplate, + ConvertedTemplateArgs, + PrevPartial); if (PrevPartial) { ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); @@ -2132,9 +2146,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), TemplateNameLoc, - ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), + ClassTemplate, + ConvertedTemplateArgs, PrevDecl); if (PrevDecl) { @@ -2255,9 +2268,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // Check that the template argument list is well-formed for this // template. - llvm::SmallVector ConvertedTemplateArgs; + TemplateArgumentListBuilder ConvertedTemplateArgs(Context); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - &TemplateArgs[0], TemplateArgs.size(), + TemplateArgs.data(), TemplateArgs.size(), RAngleLoc, ConvertedTemplateArgs)) return true; @@ -2268,8 +2281,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); + ClassTemplateSpecializationDecl::Profile(ID, + ConvertedTemplateArgs.getFlatArgumentList(), + ConvertedTemplateArgs.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -2312,9 +2326,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), - 0); + ConvertedTemplateArgs, 0); Specialization->setLexicalDeclContext(CurContext); CurContext->addDecl(Context, Specialization); return DeclPtrTy::make(Specialization); @@ -2340,9 +2352,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), - 0); + ConvertedTemplateArgs, 0); ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); @@ -2357,7 +2367,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // arguments in the specialization. QualType WrittenTy = Context.getTemplateSpecializationType(Name, - &TemplateArgs[0], + TemplateArgs.data(), TemplateArgs.size(), Context.getTypeDeclType(Specialization)); Specialization->setTypeAsWritten(WrittenTy); @@ -2563,89 +2573,3 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, << Name; return QualType(); } - -// FIXME: Move to SemaTemplateDeduction.cpp -bool -Sema::DeduceTemplateArguments(QualType Param, QualType Arg, - llvm::SmallVectorImpl &Deduced) { - // We only want to look at the canonical types, since typedefs and - // sugar are not part of template argument deduction. - Param = Context.getCanonicalType(Param); - Arg = Context.getCanonicalType(Arg); - - // If the parameter type is not dependent, just compare the types - // directly. - if (!Param->isDependentType()) - return Param == Arg; - - // FIXME: Use a visitor or switch to handle all of the kinds of - // types that the parameter may be. - if (const TemplateTypeParmType *TemplateTypeParm - = Param->getAsTemplateTypeParmType()) { - (void)TemplateTypeParm; // FIXME: use this - // The argument type can not be less qualified than the parameter - // type. - if (Param.isMoreQualifiedThan(Arg)) - return false; - - unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers(); - QualType DeducedType = Arg.getQualifiedType(Quals); - // FIXME: actually save the deduced type, and check that this - // deduction is consistent. - return true; - } - - if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) - return false; - - if (const PointerType *PointerParam = Param->getAsPointerType()) { - const PointerType *PointerArg = Arg->getAsPointerType(); - if (!PointerArg) - return false; - - return DeduceTemplateArguments(PointerParam->getPointeeType(), - PointerArg->getPointeeType(), - Deduced); - } - - // FIXME: Many more cases to go (to go). - return false; -} - -bool -Sema::DeduceTemplateArguments(const TemplateArgument &Param, - const TemplateArgument &Arg, - llvm::SmallVectorImpl &Deduced) { - assert(Param.getKind() == Arg.getKind() && - "Template argument kind mismatch during deduction"); - switch (Param.getKind()) { - case TemplateArgument::Type: - return DeduceTemplateArguments(Param.getAsType(), Arg.getAsType(), - Deduced); - - default: - return false; - } -} - -bool -Sema::DeduceTemplateArguments(const TemplateArgumentList &ParamList, - const TemplateArgumentList &ArgList, - llvm::SmallVectorImpl &Deduced) { - assert(ParamList.size() == ArgList.size()); - for (unsigned I = 0, N = ParamList.size(); I != N; ++I) { - if (!DeduceTemplateArguments(ParamList[I], ArgList[I], Deduced)) - return false; - } - return true; -} - - -bool -Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, - const TemplateArgumentList &TemplateArgs) { - llvm::SmallVector Deduced; - Deduced.resize(Partial->getTemplateParameters()->size()); - return DeduceTemplateArguments(Partial->getTemplateArgs(), TemplateArgs, - Deduced); -} diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp new file mode 100644 index 0000000..812b319 --- /dev/null +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -0,0 +1,395 @@ +//===------- SemaTemplateDeduction.cpp - Template Argument Deduction ------===/ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===/ +// +// This file implements C++ template argument deduction. +// +//===----------------------------------------------------------------------===/ + +#include "Sema.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/Parse/DeclSpec.h" +#include "llvm/Support/Compiler.h" +using namespace clang; + +/// \brief If the given expression is of a form that permits the deduction +/// of a non-type template parameter, return the declaration of that +/// non-type template parameter. +static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { + if (ImplicitCastExpr *IC = dyn_cast(E)) + E = IC->getSubExpr(); + + if (DeclRefExpr *DRE = dyn_cast(E)) + return dyn_cast(DRE->getDecl()); + + return 0; +} + +/// \brief Deduce the value of the given non-type template parameter +/// from the given constant. +/// +/// \returns true if deduction succeeded, false otherwise. +static bool DeduceNonTypeTemplateArgument(ASTContext &Context, + NonTypeTemplateParmDecl *NTTP, + llvm::APInt Value, + llvm::SmallVectorImpl &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + + if (Deduced[NTTP->getIndex()].isNull()) { + Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), + llvm::APSInt(Value), + NTTP->getType()); + return true; + } + + if (Deduced[NTTP->getIndex()].getKind() != TemplateArgument::Integral) + return false; + + // If the template argument was previously deduced to a negative value, + // then our deduction fails. + const llvm::APSInt *PrevValuePtr = Deduced[NTTP->getIndex()].getAsIntegral(); + assert(PrevValuePtr && "Not an integral template argument?"); + if (PrevValuePtr->isSigned() && PrevValuePtr->isNegative()) + return false; + + llvm::APInt PrevValue = *PrevValuePtr; + if (Value.getBitWidth() > PrevValue.getBitWidth()) + PrevValue.zext(Value.getBitWidth()); + else if (Value.getBitWidth() < PrevValue.getBitWidth()) + Value.zext(PrevValue.getBitWidth()); + return Value == PrevValue; +} + +/// \brief Deduce the value of the given non-type template parameter +/// from the given type- or value-dependent expression. +/// +/// \returns true if deduction succeeded, false otherwise. + +static bool DeduceNonTypeTemplateArgument(ASTContext &Context, + NonTypeTemplateParmDecl *NTTP, + Expr *Value, + llvm::SmallVectorImpl &Deduced) { + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument with depth > 0"); + assert((Value->isTypeDependent() || Value->isValueDependent()) && + "Expression template argument must be type- or value-dependent."); + + if (Deduced[NTTP->getIndex()].isNull()) { + // FIXME: Clone the Value? + Deduced[NTTP->getIndex()] = TemplateArgument(Value); + return true; + } + + if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Integral) { + // Okay, we deduced a constant in one case and a dependent expression + // in another case. FIXME: Later, we will check that instantiating the + // dependent expression gives us the constant value. + return true; + } + + // FIXME: Compare the expressions for equality! + return true; +} + +static bool DeduceTemplateArguments(ASTContext &Context, QualType Param, + QualType Arg, + llvm::SmallVectorImpl &Deduced) { + // We only want to look at the canonical types, since typedefs and + // sugar are not part of template argument deduction. + Param = Context.getCanonicalType(Param); + Arg = Context.getCanonicalType(Arg); + + // If the parameter type is not dependent, just compare the types + // directly. + if (!Param->isDependentType()) + return Param == Arg; + + // C++ [temp.deduct.type]p9: + // + // A template type argument T, a template template argument TT or a + // template non-type argument i can be deduced if P and A have one of + // the following forms: + // + // T + // cv-list T + if (const TemplateTypeParmType *TemplateTypeParm + = Param->getAsTemplateTypeParmType()) { + // The argument type can not be less qualified than the parameter + // type. + if (Param.isMoreQualifiedThan(Arg)) + return false; + + assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); + + unsigned Quals = Arg.getCVRQualifiers() & ~Param.getCVRQualifiers(); + QualType DeducedType = Arg.getQualifiedType(Quals); + unsigned Index = TemplateTypeParm->getIndex(); + + if (Deduced[Index].isNull()) + Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType); + else { + // C++ [temp.deduct.type]p2: + // [...] If type deduction cannot be done for any P/A pair, or if for + // any pair the deduction leads to more than one possible set of + // deduced values, or if different pairs yield different deduced + // values, or if any template argument remains neither deduced nor + // explicitly specified, template argument deduction fails. + if (Deduced[Index].getAsType() != DeducedType) + return false; + } + return true; + } + + if (Param.getCVRQualifiers() != Arg.getCVRQualifiers()) + return false; + + switch (Param->getTypeClass()) { + // No deduction possible for these types + case Type::Builtin: + return false; + + + // T * + case Type::Pointer: { + const PointerType *PointerArg = Arg->getAsPointerType(); + if (!PointerArg) + return false; + + return DeduceTemplateArguments(Context, + cast(Param)->getPointeeType(), + PointerArg->getPointeeType(), + Deduced); + } + + // T & + case Type::LValueReference: { + const LValueReferenceType *ReferenceArg = Arg->getAsLValueReferenceType(); + if (!ReferenceArg) + return false; + + return DeduceTemplateArguments(Context, + cast(Param)->getPointeeType(), + ReferenceArg->getPointeeType(), + Deduced); + } + + // T && [C++0x] + case Type::RValueReference: { + const RValueReferenceType *ReferenceArg = Arg->getAsRValueReferenceType(); + if (!ReferenceArg) + return false; + + return DeduceTemplateArguments(Context, + cast(Param)->getPointeeType(), + ReferenceArg->getPointeeType(), + Deduced); + } + + // T [] (implied, but not stated explicitly) + case Type::IncompleteArray: { + const IncompleteArrayType *IncompleteArrayArg = + Context.getAsIncompleteArrayType(Arg); + if (!IncompleteArrayArg) + return false; + + return DeduceTemplateArguments(Context, + Context.getAsIncompleteArrayType(Param)->getElementType(), + IncompleteArrayArg->getElementType(), + Deduced); + } + + // T [integer-constant] + case Type::ConstantArray: { + const ConstantArrayType *ConstantArrayArg = + Context.getAsConstantArrayType(Arg); + if (!ConstantArrayArg) + return false; + + const ConstantArrayType *ConstantArrayParm = + Context.getAsConstantArrayType(Param); + if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize()) + return false; + + return DeduceTemplateArguments(Context, + ConstantArrayParm->getElementType(), + ConstantArrayArg->getElementType(), + Deduced); + } + + // type [i] + case Type::DependentSizedArray: { + const ArrayType *ArrayArg = dyn_cast(Arg); + if (!ArrayArg) + return false; + + // Check the element type of the arrays + const DependentSizedArrayType *DependentArrayParm + = cast(Param); + if (!DeduceTemplateArguments(Context, + DependentArrayParm->getElementType(), + ArrayArg->getElementType(), + Deduced)) + return false; + + // Determine the array bound is something we can deduce. + NonTypeTemplateParmDecl *NTTP + = getDeducedParameterFromExpr(DependentArrayParm->getSizeExpr()); + if (!NTTP) + return true; + + // We can perform template argument deduction for the given non-type + // template parameter. + assert(NTTP->getDepth() == 0 && + "Cannot deduce non-type template argument at depth > 0"); + if (const ConstantArrayType *ConstantArrayArg + = dyn_cast(ArrayArg)) + return DeduceNonTypeTemplateArgument(Context, NTTP, + ConstantArrayArg->getSize(), + Deduced); + if (const DependentSizedArrayType *DependentArrayArg + = dyn_cast(ArrayArg)) + return DeduceNonTypeTemplateArgument(Context, NTTP, + DependentArrayArg->getSizeExpr(), + Deduced); + + // Incomplete type does not match a dependently-sized array type + return false; + } + + default: + break; + } + + // FIXME: Many more cases to go (to go). + return false; +} + +static bool +DeduceTemplateArguments(ASTContext &Context, const TemplateArgument &Param, + const TemplateArgument &Arg, + llvm::SmallVectorImpl &Deduced) { + switch (Param.getKind()) { + case TemplateArgument::Null: + assert(false && "Null template argument in parameter list"); + break; + + case TemplateArgument::Type: + assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch"); + return DeduceTemplateArguments(Context, Param.getAsType(), + Arg.getAsType(), Deduced); + + case TemplateArgument::Declaration: + // FIXME: Implement this check + assert(false && "Unimplemented template argument deduction case"); + return false; + + case TemplateArgument::Integral: + if (Arg.getKind() == TemplateArgument::Integral) { + // FIXME: Zero extension + sign checking here? + return *Param.getAsIntegral() == *Arg.getAsIntegral(); + } + if (Arg.getKind() == TemplateArgument::Expression) + return false; + + assert(false && "Type/value mismatch"); + return false; + + case TemplateArgument::Expression: { + if (NonTypeTemplateParmDecl *NTTP + = getDeducedParameterFromExpr(Param.getAsExpr())) { + if (Arg.getKind() == TemplateArgument::Integral) + // FIXME: Sign problems here + return DeduceNonTypeTemplateArgument(Context, NTTP, + *Arg.getAsIntegral(), Deduced); + if (Arg.getKind() == TemplateArgument::Expression) + return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(), + Deduced); + + assert(false && "Type/value mismatch"); + return false; + } + + // Can't deduce anything, but that's okay. + return true; + } + } + + return true; +} + +static bool +DeduceTemplateArguments(ASTContext &Context, + const TemplateArgumentList &ParamList, + const TemplateArgumentList &ArgList, + llvm::SmallVectorImpl &Deduced) { + assert(ParamList.size() == ArgList.size()); + for (unsigned I = 0, N = ParamList.size(); I != N; ++I) { + if (!DeduceTemplateArguments(Context, ParamList[I], ArgList[I], Deduced)) + return false; + } + return true; +} + + +TemplateArgumentList * +Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, + const TemplateArgumentList &TemplateArgs) { + // Deduce the template arguments for the partial specialization + llvm::SmallVector Deduced; + Deduced.resize(Partial->getTemplateParameters()->size()); + if (! ::DeduceTemplateArguments(Context, Partial->getTemplateArgs(), + TemplateArgs, Deduced)) + return 0; + + // FIXME: Substitute the deduced template arguments into the template + // arguments of the class template partial specialization; the resulting + // template arguments should match TemplateArgs exactly. + + for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { + TemplateArgument &Arg = Deduced[I]; + + // FIXME: If this template argument was not deduced, but the corresponding + // template parameter has a default argument, instantiate the default + // argument. + if (Arg.isNull()) // FIXME: Result->Destroy(Context); + return 0; + + if (Arg.getKind() == TemplateArgument::Integral) { + // FIXME: Instantiate the type, but we need some context! + const NonTypeTemplateParmDecl *Parm + = cast(Partial->getTemplateParameters() + ->getParam(I)); + // QualType T = InstantiateType(Parm->getType(), *Result, + // Parm->getLocation(), Parm->getDeclName()); + // if (T.isNull()) // FIXME: Result->Destroy(Context); + // return 0; + QualType T = Parm->getType(); + + // FIXME: Make sure we didn't overflow our data type! + llvm::APSInt &Value = *Arg.getAsIntegral(); + unsigned AllowedBits = Context.getTypeSize(T); + if (Value.getBitWidth() != AllowedBits) + Value.extOrTrunc(AllowedBits); + Value.setIsSigned(T->isSignedIntegerType()); + Arg.setIntegralType(T); + } + } + + // FIXME: This is terrible. DeduceTemplateArguments should use a + // TemplateArgumentListBuilder directly. + TemplateArgumentListBuilder Builder(Context); + for (unsigned I = 0, N = Deduced.size(); I != N; ++I) + Builder.push_back(Deduced[I]); + + return new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true, + /*FlattenArgs=*/true); +} diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index d3d771b..562749e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -503,6 +503,10 @@ InstantiateTemplateSpecializationType( for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end(); Arg != ArgEnd; ++Arg) { switch (Arg->getKind()) { + case TemplateArgument::Null: + assert(false && "Should never have a NULL template argument"); + break; + case TemplateArgument::Type: { QualType T = SemaRef.InstantiateType(Arg->getAsType(), TemplateArgs, @@ -829,21 +833,23 @@ Sema::InstantiateClassTemplateSpecialization( // Determine whether any class template partial specializations // match the given template arguments. - llvm::SmallVector Matched; + typedef std::pair MatchResult; + llvm::SmallVector Matched; for (llvm::FoldingSet::iterator Partial = Template->getPartialSpecializations().begin(), PartialEnd = Template->getPartialSpecializations().end(); Partial != PartialEnd; ++Partial) { - if (DeduceTemplateArguments(&*Partial, ClassTemplateSpec->getTemplateArgs())) - Matched.push_back(&*Partial); + if (TemplateArgumentList *Deduced + = DeduceTemplateArguments(&*Partial, + ClassTemplateSpec->getTemplateArgs())) + Matched.push_back(std::make_pair(&*Partial, Deduced)); } if (Matched.size() == 1) { - Pattern = Matched[0]; - // FIXME: set TemplateArgs to the template arguments of the - // partial specialization, instantiated with the deduced template - // arguments. + Pattern = Matched[0].first; + TemplateArgs = Matched[0].second; } else if (Matched.size() > 1) { // FIXME: Implement partial ordering of class template partial // specializations. @@ -856,9 +862,17 @@ Sema::InstantiateClassTemplateSpecialization( ExplicitInstantiation? TSK_ExplicitInstantiation : TSK_ImplicitInstantiation); - return InstantiateClass(ClassTemplateSpec->getLocation(), - ClassTemplateSpec, Pattern, *TemplateArgs, - ExplicitInstantiation); + bool Result = InstantiateClass(ClassTemplateSpec->getLocation(), + ClassTemplateSpec, Pattern, *TemplateArgs, + ExplicitInstantiation); + + for (unsigned I = 0, N = Matched.size(); I != N; ++I) { + // FIXME: Implement TemplateArgumentList::Destroy! + // if (Matched[I].first != Pattern) + // Matched[I].second->Destroy(Context); + } + + return Result; } /// \brief Instantiate the definitions of all of the member of the diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index a6b9703..5ba42f2 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -119,12 +119,13 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { T->isWideCharType(), T, E->getSourceRange().getBegin())); - else if (T->isBooleanType()) + if (T->isBooleanType()) return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr( Arg.getAsIntegral()->getBoolValue(), T, E->getSourceRange().getBegin())); + assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T)); return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( *Arg.getAsIntegral(), T, diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp index 1f69479..fd349df 100644 --- a/lib/Sema/SemaTemplateInstantiateStmt.cpp +++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp @@ -194,6 +194,8 @@ Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) { if (Cond.isInvalid()) return SemaRef.StmtError(); + Sema::FullExprArg FullCond(FullExpr(Cond)); + // Instantiate the "then" branch. OwningStmtResult Then = SemaRef.InstantiateStmt(S->getThen(), TemplateArgs); if (Then.isInvalid()) @@ -204,7 +206,7 @@ Sema::OwningStmtResult TemplateStmtInstantiator::VisitIfStmt(IfStmt *S) { if (Else.isInvalid()) return SemaRef.StmtError(); - return SemaRef.ActOnIfStmt(S->getIfLoc(), FullExpr(Cond), move(Then), + return SemaRef.ActOnIfStmt(S->getIfLoc(), FullCond, move(Then), S->getElseLoc(), move(Else)); } @@ -236,12 +238,14 @@ Sema::OwningStmtResult TemplateStmtInstantiator::VisitWhileStmt(WhileStmt *S) { if (Cond.isInvalid()) return SemaRef.StmtError(); + Sema::FullExprArg FullCond(FullExpr(Cond)); + // Instantiate the body OwningStmtResult Body = SemaRef.InstantiateStmt(S->getBody(), TemplateArgs); if (Body.isInvalid()) return SemaRef.StmtError(); - return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullExpr(Cond), move(Body)); + return SemaRef.ActOnWhileStmt(S->getWhileLoc(), FullCond, move(Body)); } Sema::OwningStmtResult TemplateStmtInstantiator::VisitDoStmt(DoStmt *S) { -- cgit v1.1