diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-11-04 15:04:32 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-11-04 15:04:32 +0000 |
commit | b6d5e15aae202f157c6cd63da8fa4b089e7b31e9 (patch) | |
tree | 59e0e47a9831dcf0e21e547927c8ebb7e113bfd1 /lib/Sema | |
parent | 5563df30b9c8d1fe87a54baae0d6bd86642563f4 (diff) | |
download | FreeBSD-src-b6d5e15aae202f157c6cd63da8fa4b089e7b31e9.zip FreeBSD-src-b6d5e15aae202f157c6cd63da8fa4b089e7b31e9.tar.gz |
Update clang to r86025.
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 217 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 95 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 261 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 100 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 114 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 70 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 490 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 186 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 244 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 439 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 161 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 381 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 395 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 265 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 896 |
21 files changed, 2714 insertions, 1693 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index c78ab5b..9b24d55 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -156,6 +156,17 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, case Result::RK_Keyword: OS << Results[I].Keyword << " : " << Results[I].Rank << '\n'; break; + + case Result::RK_Macro: { + OS << Results[I].Macro->getName() << " : " << Results[I].Rank; + if (CodeCompletionString *CCS + = Results[I].CreateCodeCompletionString(SemaRef)) { + OS << " : " << CCS->getAsString(); + delete CCS; + } + OS << '\n'; + break; + } } } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index fc9c14f..8104dd3 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -277,15 +277,20 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { PushDeclContext(S, Context.getTranslationUnitDecl()); if (PP.getTargetInfo().getPointerWidth(0) >= 64) { + DeclaratorInfo *DInfo; + // Install [u]int128_t for 64-bit targets. + DInfo = Context.getTrivialDeclaratorInfo(Context.Int128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("__int128_t"), - Context.Int128Ty), TUScope); + DInfo), TUScope); + + DInfo = Context.getTrivialDeclaratorInfo(Context.UnsignedInt128Ty); PushOnScopeChains(TypedefDecl::Create(Context, CurContext, SourceLocation(), &Context.Idents.get("__uint128_t"), - Context.UnsignedInt128Ty), TUScope); + DInfo), TUScope); } @@ -298,10 +303,10 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { PushOnScopeChains(SelTag, TUScope); QualType SelT = Context.getPointerType(Context.getTagDeclType(SelTag)); - TypedefDecl *SelTypedef = TypedefDecl::Create(Context, CurContext, - SourceLocation(), - &Context.Idents.get("SEL"), - SelT); + DeclaratorInfo *SelInfo = Context.getTrivialDeclaratorInfo(SelT); + TypedefDecl *SelTypedef + = TypedefDecl::Create(Context, CurContext, SourceLocation(), + &Context.Idents.get("SEL"), SelInfo); PushOnScopeChains(SelTypedef, TUScope); Context.setObjCSelType(Context.getTypeDeclType(SelTypedef)); } @@ -317,22 +322,23 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { } // Create the built-in typedef for 'id'. if (Context.getObjCIdType().isNull()) { - TypedefDecl *IdTypedef = - TypedefDecl::Create( - Context, CurContext, SourceLocation(), &Context.Idents.get("id"), - Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy) - ); + QualType IdT = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy); + DeclaratorInfo *IdInfo = Context.getTrivialDeclaratorInfo(IdT); + TypedefDecl *IdTypedef + = TypedefDecl::Create(Context, CurContext, SourceLocation(), + &Context.Idents.get("id"), IdInfo); PushOnScopeChains(IdTypedef, TUScope); Context.setObjCIdType(Context.getTypeDeclType(IdTypedef)); Context.ObjCIdRedefinitionType = Context.getObjCIdType(); } // Create the built-in typedef for 'Class'. if (Context.getObjCClassType().isNull()) { - TypedefDecl *ClassTypedef = - TypedefDecl::Create( - Context, CurContext, SourceLocation(), &Context.Idents.get("Class"), - Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy) - ); + QualType ClassType + = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy); + DeclaratorInfo *ClassInfo = Context.getTrivialDeclaratorInfo(ClassType); + TypedefDecl *ClassTypedef + = TypedefDecl::Create(Context, CurContext, SourceLocation(), + &Context.Idents.get("Class"), ClassInfo); PushOnScopeChains(ClassTypedef, TUScope); Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef)); Context.ObjCClassRedefinitionType = Context.getObjCClassType(); @@ -344,7 +350,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, : LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CodeCompleter(0), CurContext(0), - PreDeclaratorDC(0), CurBlock(0), PackContext(0), + PreDeclaratorDC(0), CurBlock(0), PackContext(0), ParsingDeclDepth(0), IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated), CompleteTranslationUnit(CompleteTranslationUnit), diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 6dd081b..0f84b46 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -73,6 +73,7 @@ namespace clang { class TypedefDecl; class TemplateDecl; class TemplateArgument; + class TemplateArgumentLoc; class TemplateArgumentList; class TemplateParameterList; class TemplateTemplateParmDecl; @@ -271,6 +272,15 @@ public: llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions; std::vector<DeclarationName> TentativeDefinitionList; + /// \brief The collection of delayed deprecation warnings. + llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8> + DelayedDeprecationWarnings; + + /// \brief The depth of the current ParsingDeclaration stack. + /// If nonzero, we are currently parsing a declaration (and + /// hence should delay deprecation warnings). + unsigned ParsingDeclDepth; + /// WeakUndeclaredIdentifiers - Identifiers contained in /// #pragma weak before declared. rare. may alias another /// identifier, declared or undeclared @@ -447,8 +457,6 @@ public: // Type Analysis / Processing: SemaType.cpp. // QualType adjustParameterType(QualType T); - QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc, - bool &IsInvalid); void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL); QualType BuildPointerType(QualType T, unsigned Quals, SourceLocation Loc, DeclarationName Entity); @@ -470,12 +478,12 @@ public: SourceLocation Loc, DeclarationName Entity); QualType GetTypeForDeclarator(Declarator &D, Scope *S, DeclaratorInfo **DInfo = 0, - unsigned Skip = 0, TagDecl **OwnedDecl = 0); - DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, - unsigned Skip); + TagDecl **OwnedDecl = 0); + DeclaratorInfo *GetDeclaratorInfoForDeclarator(Declarator &D, QualType T); /// \brief Create a LocInfoType to hold the given QualType and DeclaratorInfo. QualType CreateLocInfoType(QualType T, DeclaratorInfo *DInfo); DeclarationName GetNameForDeclarator(Declarator &D); + DeclarationName GetNameFromUnqualifiedId(UnqualifiedId &Name); static QualType GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo = 0); bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); @@ -767,7 +775,8 @@ public: /// Subroutines of ActOnDeclarator(). - TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T); + TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + DeclaratorInfo *DInfo); void MergeTypeDefDecl(TypedefDecl *New, Decl *Old); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); @@ -868,7 +877,7 @@ public: bool ForceRValue = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -876,7 +885,7 @@ public: bool ForceRValue = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -914,7 +923,7 @@ public: void AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading = false); @@ -936,7 +945,7 @@ public: DeclarationName &UnqualifiedName, bool &ArgumentDependentLookup, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, @@ -945,7 +954,7 @@ public: FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, DeclarationName UnqualifiedName, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -963,6 +972,10 @@ public: FunctionSet &Functions, Expr *LHS, Expr *RHS); + OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, + ExprArg Base,ExprArg Idx); + ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr, SourceLocation LParenLoc, Expr **Args, @@ -990,7 +1003,7 @@ public: void CheckCXXDefaultArguments(FunctionDecl *FD); void CheckExtraCXXDefaultArguments(Declarator &D); enum ControlFlowKind { NeverFallThrough = 0, MaybeFallThrough = 1, - AlwaysFallThrough = 2 }; + AlwaysFallThrough = 2, NeverFallThroughOrReturn = 3 }; ControlFlowKind CheckFallThrough(Stmt *); Scope *getNonFieldDeclScope(Scope *S); @@ -1377,7 +1390,7 @@ public: QualType T1, QualType T2, FunctionSet &Functions); - void ArgumentDependentLookup(DeclarationName Name, + void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, FunctionSet &Functions); @@ -1582,6 +1595,10 @@ public: /// whose result is unused, warn. void DiagnoseUnusedExprResult(const Stmt *S); + ParsingDeclStackState PushParsingDeclaration(); + void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D); + void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc); + //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. @@ -1604,23 +1621,12 @@ public: // Primary Expressions. virtual SourceRange getExprRange(ExprTy *E) const; - virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen, - const CXXScopeSpec *SS = 0, - bool isAddressOfOperand = false); - virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(Scope *S, - SourceLocation OperatorLoc, - OverloadedOperatorKind Op, - bool HasTrailingLParen, - const CXXScopeSpec &SS, - bool isAddressOfOperand); - virtual OwningExprResult ActOnCXXConversionFunctionExpr(Scope *S, - SourceLocation OperatorLoc, - TypeTy *Ty, - bool HasTrailingLParen, - const CXXScopeSpec &SS, - bool isAddressOfOperand); + virtual OwningExprResult ActOnIdExpression(Scope *S, + const CXXScopeSpec &SS, + UnqualifiedId &Name, + bool HasTrailingLParen, + bool IsAddressOfOperand); + OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, bool TypeDependent, bool ValueDependent, @@ -1664,7 +1670,8 @@ public: virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, ExprArg Input); - OwningExprResult CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc, + OwningExprResult CreateSizeOfAlignOfExpr(DeclaratorInfo *T, + SourceLocation OpLoc, bool isSizeOf, SourceRange R); OwningExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, bool isSizeOf, SourceRange R); @@ -1684,6 +1691,10 @@ public: SourceLocation LLoc, ExprArg Idx, SourceLocation RLoc); + OwningExprResult CreateBuiltinArraySubscriptExpr(ExprArg Base, + SourceLocation LLoc, + ExprArg Idx, + SourceLocation RLoc); OwningExprResult BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, @@ -1709,20 +1720,21 @@ public: DeclarationName MemberName, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, DeclPtrTy ImplDecl, const CXXScopeSpec *SS, NamedDecl *FirstQualifierInScope = 0); - virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation MemberLoc, - IdentifierInfo &Member, - DeclPtrTy ImplDecl, - const CXXScopeSpec *SS = 0); + virtual OwningExprResult ActOnMemberAccessExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + UnqualifiedId &Member, + DeclPtrTy ObjCImpDecl, + bool HasTrailingLParen); + virtual void ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl); bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, FunctionDecl *FDecl, @@ -1742,7 +1754,7 @@ public: SourceRange &QualifierRange, bool &ArgumentDependentLookup, bool &HasExplicitTemplateArguments, - const TemplateArgument *&ExplicitTemplateArgs, + const TemplateArgumentLoc *&ExplicitTemplateArgs, unsigned &NumExplicitTemplateArgs); /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. @@ -1900,7 +1912,6 @@ public: /// and sets it as the initializer for the the passed in VarDecl. bool InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, - QualType DeclInitType, MultiExprArg Exprs); /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -2099,52 +2110,6 @@ public: tok::TokenKind OpKind, TypeTy *&ObjectType); - virtual OwningExprResult - ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - IdentifierInfo *ClassName, - const CXXScopeSpec &SS, - bool HasTrailingLParen); - - virtual OwningExprResult - ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceRange TypeRange, - TypeTy *Type, - const CXXScopeSpec &SS, - bool HasTrailingLParen); - - virtual OwningExprResult - ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - OverloadedOperatorKind OverOpKind, - const CXXScopeSpec *SS = 0); - virtual OwningExprResult - ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - TypeTy *Ty, - const CXXScopeSpec *SS = 0); - - virtual OwningExprResult - ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - // FIXME: "template" keyword? - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc); - /// MaybeCreateCXXExprWithTemporaries - If the list of temporaries is /// non-empty, will create a new CXXExprWithTemporaries expression. /// Otherwise, just returs the passed in expression. @@ -2305,7 +2270,7 @@ public: SourceLocation RParenLoc, CXXRecordDecl *ClassDecl); - void setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, + void SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, @@ -2445,9 +2410,8 @@ public: // C++ Templates [C++ 14] // virtual TemplateNameKind isTemplateName(Scope *S, - const IdentifierInfo &II, - SourceLocation IdLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType, bool EnteringContext, TemplateTy &Template); @@ -2507,13 +2471,13 @@ public: AccessSpecifier AS); void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocs, - llvm::SmallVector<TemplateArgument, 16> &TemplateArgs); + SourceLocation *TemplateArgLocsIn, + llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs); QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); @@ -2534,22 +2498,21 @@ public: TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc); - virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc); + OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc); virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - const IdentifierInfo &Name, - SourceLocation NameLoc, const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType); bool CheckClassTemplatePartialSpecializationArgs( @@ -2578,10 +2541,18 @@ public: MultiTemplateParamsArg TemplateParameterLists, Declarator &D); + bool + CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, + TemplateSpecializationKind NewTSK, + NamedDecl *PrevDecl, + TemplateSpecializationKind PrevTSK, + SourceLocation PrevPointOfInstantiation, + bool &SuppressNew); + bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, NamedDecl *&PrevDecl); @@ -2621,18 +2592,18 @@ public: bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - const TemplateArgument &Arg, + const TemplateArgumentLoc &Arg, TemplateArgumentListBuilder &Converted); - bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg, - SourceLocation ArgLoc); + bool CheckTemplateArgument(TemplateTypeParmDecl *Param, + DeclaratorInfo *Arg); bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, NamedDecl *&Entity); bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member); @@ -2807,7 +2778,7 @@ public: TemplateDeductionResult SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, @@ -2823,7 +2794,7 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, @@ -2832,7 +2803,7 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, @@ -2863,6 +2834,7 @@ public: void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used); void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, llvm::SmallVectorImpl<bool> &Deduced); @@ -3101,7 +3073,7 @@ public: llvm::DenseMap<const Decl *, Decl *> LocalDecls; /// \brief The outer scope, in which contains local variable - /// definitions from some other instantiation (that is not + /// definitions from some other instantiation (that may not be /// relevant to this particular scope). LocalInstantiationScope *Outer; @@ -3110,9 +3082,13 @@ public: LocalInstantiationScope &operator=(const LocalInstantiationScope &); public: - LocalInstantiationScope(Sema &SemaRef) + LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope) { - SemaRef.CurrentInstantiationScope = this; + if (!CombineWithOuterScope) + SemaRef.CurrentInstantiationScope = this; + else + assert(SemaRef.CurrentInstantiationScope && + "No outer instantiation scope?"); } ~LocalInstantiationScope() { @@ -3133,6 +3109,11 @@ public: return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var))); } + NonTypeTemplateParmDecl *getInstantiationOf( + const NonTypeTemplateParmDecl *Var) { + return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var))); + } + void InstantiatedLocal(const Decl *D, Decl *Inst) { Decl *&Stored = LocalDecls[D]; assert(!Stored && "Already instantiated this local"); @@ -3190,7 +3171,7 @@ public: bool Complain = true); bool - InstantiateClassTemplateSpecialization( + InstantiateClassTemplateSpecialization(SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK, bool Complain = true); @@ -3213,8 +3194,8 @@ public: TemplateName SubstTemplateName(TemplateName Name, SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs); - TemplateArgument Subst(TemplateArgument Arg, - const MultiLevelTemplateArgumentList &TemplateArgs); + bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result, + const MultiLevelTemplateArgumentList &TemplateArgs); void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index bf39604..8bb3348 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -83,7 +83,8 @@ static TryCastResult TryStaticDowncast(Sema &Self, QualType SrcType, static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType,bool CStyle, const SourceRange &OpRange, - unsigned &msg); + unsigned &msg, + CastExpr::CastKind &Kind); static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, const SourceRange &OpRange, @@ -480,7 +481,7 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr, // conversion. C++ 5.2.9p9 has additional information. // DR54's access restrictions apply here also. tcr = TryStaticMemberPointerUpcast(Self, SrcType, DestType, CStyle, - OpRange, msg); + OpRange, msg, Kind); if (tcr != TC_NotApplicable) return tcr; @@ -706,7 +707,7 @@ TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType, TryCastResult TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, bool CStyle, const SourceRange &OpRange, - unsigned &msg) { + unsigned &msg, CastExpr::CastKind &Kind) { const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>(); if (!DestMemPtr) return TC_NotApplicable; @@ -760,6 +761,7 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, return TC_Failed; } + Kind = CastExpr::CK_DerivedToBaseMemberPointer; return TC_Success; } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 589b0c6..38b6ebe 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -1272,10 +1272,15 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, // Skip over implicit cast expressions when checking for block expressions. RetValExp = RetValExp->IgnoreParenCasts(); - if (BlockExpr *C = dyn_cast_or_null<BlockExpr>(RetValExp)) + if (BlockExpr *C = dyn_cast<BlockExpr>(RetValExp)) if (C->hasBlockDeclRefExprs()) Diag(C->getLocStart(), diag::err_ret_local_block) << C->getSourceRange(); + + if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp)) + Diag(ALE->getLocStart(), diag::warn_ret_addr_label) + << ALE->getSourceRange(); + } else if (lhsType->isReferenceType()) { // Perform checking for stack values returned by reference. // Check for a reference to the stack @@ -1420,8 +1425,7 @@ static DeclRefExpr* EvalVal(Expr *E) { // viewed AST node. We then recursively traverse the AST by calling // EvalAddr and EvalVal appropriately. switch (E->getStmtClass()) { - case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: { + case Stmt::DeclRefExprClass: { // DeclRefExpr: the base case. When we hit a DeclRefExpr we are looking // at code that refers to a variable's name. We check if it has local // storage within the function, and if so, return the expression. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3811513..e9df17d 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -13,6 +13,8 @@ #include "Sema.h" #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/AST/ExprCXX.h" +#include "clang/Lex/MacroInfo.h" +#include "clang/Lex/Preprocessor.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" #include <list> @@ -801,9 +803,45 @@ void AddQualifierToCompletionString(CodeCompletionString *Result, /// result is all that is needed. CodeCompletionString * CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { - if (Kind != RK_Declaration) + if (Kind == RK_Keyword) return 0; + if (Kind == RK_Macro) { + MacroInfo *MI = S.PP.getMacroInfo(Macro); + if (!MI || !MI->isFunctionLike()) + return 0; + + // Format a function-like macro with placeholders for the arguments. + CodeCompletionString *Result = new CodeCompletionString; + Result->AddTextChunk(Macro->getName().str().c_str()); + Result->AddTextChunk("("); + for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); + A != AEnd; ++A) { + if (A != MI->arg_begin()) + Result->AddTextChunk(", "); + + if (!MI->isVariadic() || A != AEnd - 1) { + // Non-variadic argument. + Result->AddPlaceholderChunk((*A)->getName().str().c_str()); + continue; + } + + // Variadic argument; cope with the different between GNU and C99 + // variadic macros, providing a single placeholder for the rest of the + // arguments. + if ((*A)->isStr("__VA_ARGS__")) + Result->AddPlaceholderChunk("..."); + else { + std::string Arg = (*A)->getName(); + Arg += "..."; + Result->AddPlaceholderChunk(Arg.c_str()); + } + } + Result->AddTextChunk(")"); + return Result; + } + + assert(Kind == RK_Declaration && "Missed a macro kind?"); NamedDecl *ND = Declaration; if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { @@ -999,6 +1037,10 @@ namespace { case Result::RK_Keyword: return strcmp(X.Keyword, Y.Keyword) < 0; + + case Result::RK_Macro: + return llvm::LowercaseString(X.Macro->getName()) < + llvm::LowercaseString(Y.Macro->getName()); } // Silence GCC warning. @@ -1007,6 +1049,16 @@ namespace { }; } +// Add all of the known macros as code-completion results. +static void AddMacroResults(Preprocessor &PP, unsigned Rank, + ResultBuilder &Results) { + Results.EnterNewScope(); + for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); + M != MEnd; ++M) + Results.MaybeAddResult(CodeCompleteConsumer::Result(M->first, Rank)); + Results.ExitScope(); +} + static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter, CodeCompleteConsumer::Result *Results, unsigned NumResults) { @@ -1019,8 +1071,9 @@ static void HandleCodeCompleteResults(CodeCompleteConsumer *CodeCompleter, void Sema::CodeCompleteOrdinaryName(Scope *S) { ResultBuilder Results(*this, &ResultBuilder::IsOrdinaryName); - CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, - Results); + unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + 0, CurContext, Results); + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1076,6 +1129,9 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE, CurContext, Results); } + // Add macros + AddMacroResults(PP, NextRank, Results); + // Hand off the results found for code completion. HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); @@ -1117,10 +1173,11 @@ void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { // We could have the start of a nested-name-specifier. Add those // results as well. Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank, - CurContext, Results); + NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + NextRank, CurContext, Results); } + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1171,8 +1228,7 @@ void Sema::CodeCompleteCase(Scope *S) { // At the XXX, our completions are TagDecl::TK_union, // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, // TK_struct, and TK_class. - if (QualifiedDeclRefExpr *QDRE = dyn_cast<QualifiedDeclRefExpr>(DRE)) - Qualifier = QDRE->getQualifier(); + Qualifier = DRE->getQualifier(); } } @@ -1199,6 +1255,7 @@ void Sema::CodeCompleteCase(Scope *S) { } Results.ExitScope(); + AddMacroResults(PP, 1, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1235,7 +1292,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, SourceRange QualifierRange; bool ArgumentDependentLookup; bool HasExplicitTemplateArgs; - const TemplateArgument *ExplicitTemplateArgs; + const TemplateArgumentLoc *ExplicitTemplateArgs; unsigned NumExplicitTemplateArgs; DeconstructCallFunction(Fn, @@ -1293,6 +1350,7 @@ void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS, if (!Results.empty() && NNS->isDependent()) Results.MaybeAddResult(CodeCompleteConsumer::Result("template", NextRank)); + AddMacroResults(PP, NextRank + 1, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1309,10 +1367,11 @@ void Sema::CodeCompleteUsing(Scope *S) { // After "using", we can see anything that would start a // nested-name-specifier. - CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, - CurContext, Results); + unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + 0, CurContext, Results); Results.ExitScope(); + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1324,9 +1383,10 @@ void Sema::CodeCompleteUsingDirective(Scope *S) { // alias. ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); Results.EnterNewScope(); - CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, - Results); + unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + 0, CurContext, Results); Results.ExitScope(); + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1361,6 +1421,7 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) { Results.ExitScope(); } + AddMacroResults(PP, 1, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1370,8 +1431,9 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { // After "namespace", we expect to see a namespace or alias. ResultBuilder Results(*this, &ResultBuilder::IsNamespaceOrAlias); - CollectLookupResults(S, Context.getTranslationUnitDecl(), 0, CurContext, - Results); + unsigned NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + 0, CurContext, Results); + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } @@ -1398,10 +1460,11 @@ void Sema::CodeCompleteOperatorName(Scope *S) { // Add any nested-name-specifiers Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); - CollectLookupResults(S, Context.getTranslationUnitDecl(), NextRank + 1, - CurContext, Results); + NextRank = CollectLookupResults(S, Context.getTranslationUnitDecl(), + NextRank + 1, CurContext, Results); Results.ExitScope(); + AddMacroResults(PP, NextRank, Results); HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size()); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b83181b..d89cb5f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -95,7 +95,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::FoundOverloaded: return 0; - case LookupResult::Ambiguous: { + case LookupResult::Ambiguous: // Recover from type-hiding ambiguities by hiding the type. We'll // do the lookup again when looking for an object, and we can // diagnose the error then. If we don't do this, then the error @@ -131,51 +131,43 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, // perform the name lookup again. DiagnoseAmbiguousLookup(Result, DeclarationName(&II), NameLoc); break; - } case LookupResult::Found: IIDecl = Result.getFoundDecl(); break; } - if (IIDecl) { - QualType T; - - if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { - // Check whether we can use this type - (void)DiagnoseUseOfDecl(IIDecl, NameLoc); - - if (getLangOptions().CPlusPlus) { - // C++ [temp.local]p2: - // Within the scope of a class template specialization or - // partial specialization, when the injected-class-name is - // not followed by a <, it is equivalent to the - // injected-class-name followed by the template-argument s - // of the class template specialization or partial - // specialization enclosed in <>. - if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) - if (RD->isInjectedClassName()) - if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate()) - T = Template->getInjectedClassNameType(Context); - } - - if (T.isNull()) - T = Context.getTypeDeclType(TD); - } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { - // Check whether we can use this interface. - (void)DiagnoseUseOfDecl(IIDecl, NameLoc); - - T = Context.getObjCInterfaceType(IDecl); - } else - return 0; + assert(IIDecl && "Didn't find decl"); + QualType T; + if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); + + // C++ [temp.local]p2: + // Within the scope of a class template specialization or + // partial specialization, when the injected-class-name is + // not followed by a <, it is equivalent to the + // injected-class-name followed by the template-argument s + // of the class template specialization or partial + // specialization enclosed in <>. + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) + if (RD->isInjectedClassName()) + if (ClassTemplateDecl *Template = RD->getDescribedClassTemplate()) + T = Template->getInjectedClassNameType(Context); + + if (T.isNull()) + T = Context.getTypeDeclType(TD); + if (SS) T = getQualifiedNameType(*SS, T); + + } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { + DiagnoseUseOfDecl(IIDecl, NameLoc); + T = Context.getObjCInterfaceType(IDecl); + } else + return 0; - return T.getAsOpaquePtr(); - } - - return 0; + return T.getAsOpaquePtr(); } /// isTagName() - This method is called *for error recovery purposes only* @@ -1055,9 +1047,11 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) { /// Statement that should return a value. /// /// \returns AlwaysFallThrough iff we always fall off the end of the statement, -/// MaybeFallThrough iff we might or might not fall off the end and -/// NeverFallThrough iff we never fall off the end of the statement. We assume -/// that functions not marked noreturn will return. +/// MaybeFallThrough iff we might or might not fall off the end, +/// NeverFallThroughOrReturn iff we never fall off the end of the statement or +/// return. We assume NeverFallThrough iff we never fall off the end of the +/// statement but we may return. We assume that functions not marked noreturn +/// will return. Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { // FIXME: Eventually share this CFG object when we have other warnings based // of the CFG. This can be done using AnalysisContext. @@ -1065,7 +1059,8 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { // FIXME: They should never return 0, fix that, delete this code. if (cfg == 0) - return NeverFallThrough; + // FIXME: This should be NeverFallThrough + return NeverFallThroughOrReturn; // The CFG leaves in dead things, and we don't want to dead code paths to // confuse us, so we mark all live things first. std::queue<CFGBlock*> workq; @@ -1094,7 +1089,7 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { bool HasLiveReturn = false; bool HasFakeEdge = false; bool HasPlainEdge = false; - for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(), + for (CFGBlock::pred_iterator I=cfg->getExit().pred_begin(), E = cfg->getExit().pred_end(); I != E; ++I) { @@ -1138,8 +1133,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { if (NoReturnEdge == false) HasPlainEdge = true; } - if (!HasPlainEdge) - return NeverFallThrough; + if (!HasPlainEdge) { + if (HasLiveReturn) + return NeverFallThrough; + return NeverFallThroughOrReturn; + } if (HasFakeEdge || HasLiveReturn) return MaybeFallThrough; // This says AlwaysFallThrough for calls to functions that are not marked @@ -1161,6 +1159,7 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) { // which this code would then warn about. if (getDiagnostics().hasErrorOccurred()) return; + bool ReturnsVoid = false; bool HasNoReturn = false; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -1202,10 +1201,12 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) { else if (!ReturnsVoid) Diag(Compound->getRBracLoc(), diag::warn_falloff_nonvoid_function); break; - case NeverFallThrough: - if (ReturnsVoid) + case NeverFallThroughOrReturn: + if (ReturnsVoid && !HasNoReturn) Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_function); break; + case NeverFallThrough: + break; } } } @@ -1225,7 +1226,7 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) { return; bool ReturnsVoid = false; bool HasNoReturn = false; - if (const FunctionType *FT = BlockTy->getPointeeType()->getAs<FunctionType>()) { + if (const FunctionType *FT =BlockTy->getPointeeType()->getAs<FunctionType>()){ if (FT->getResultType()->isVoidType()) ReturnsVoid = true; if (FT->getNoReturnAttr()) @@ -1253,10 +1254,12 @@ void Sema::CheckFallThroughForBlock(QualType BlockTy, Stmt *Body) { else if (!ReturnsVoid) Diag(Compound->getRBracLoc(), diag::err_falloff_nonvoid_block); break; - case NeverFallThrough: + case NeverFallThroughOrReturn: if (ReturnsVoid) Diag(Compound->getLBracLoc(), diag::warn_suggest_noreturn_block); break; + case NeverFallThrough: + break; } } } @@ -1330,6 +1333,10 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { } if (RecordDecl *Record = dyn_cast_or_null<RecordDecl>(Tag)) { + // If there are attributes in the DeclSpec, apply them to the record. + if (const AttributeList *AL = DS.getAttributes()) + ProcessDeclAttributeList(S, Record, AL); + if (!Record->getDeclName() && Record->isDefinition() && DS.getStorageClassSpec() != DeclSpec::SCS_typedef) { if (getLangOptions().CPlusPlus || @@ -1602,53 +1609,60 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, /// GetNameForDeclarator - Determine the full declaration name for the /// given Declarator. DeclarationName Sema::GetNameForDeclarator(Declarator &D) { - switch (D.getKind()) { - case Declarator::DK_Abstract: - assert(D.getIdentifier() == 0 && "abstract declarators have no name"); - return DeclarationName(); - - case Declarator::DK_Normal: - assert (D.getIdentifier() != 0 && "normal declarators have an identifier"); - return DeclarationName(D.getIdentifier()); - - case Declarator::DK_Constructor: { - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); - return Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(Ty)); - } - - case Declarator::DK_Destructor: { - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); - return Context.DeclarationNames.getCXXDestructorName( - Context.getCanonicalType(Ty)); - } - - case Declarator::DK_Conversion: { - // FIXME: We'd like to keep the non-canonical type for diagnostics! - QualType Ty = GetTypeFromParser(D.getDeclaratorIdType()); - return Context.DeclarationNames.getCXXConversionFunctionName( - Context.getCanonicalType(Ty)); - } + return GetNameFromUnqualifiedId(D.getName()); +} - case Declarator::DK_Operator: - assert(D.getIdentifier() == 0 && "operator names have no identifier"); - return Context.DeclarationNames.getCXXOperatorName( - D.getOverloadedOperator()); +/// \brief Retrieves the canonicalized name from a parsed unqualified-id. +DeclarationName Sema::GetNameFromUnqualifiedId(UnqualifiedId &Name) { + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + return DeclarationName(Name.Identifier); - case Declarator::DK_TemplateId: { - TemplateName Name - = TemplateName::getFromVoidPointer(D.getTemplateId()->Template); - if (TemplateDecl *Template = Name.getAsTemplateDecl()) - return Template->getDeclName(); - if (OverloadedFunctionDecl *Ovl = Name.getAsOverloadedFunctionDecl()) - return Ovl->getDeclName(); - - return DeclarationName(); - } + case UnqualifiedId::IK_OperatorFunctionId: + return Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); + + case UnqualifiedId::IK_ConversionFunctionId: { + QualType Ty = GetTypeFromParser(Name.ConversionFunctionId); + if (Ty.isNull()) + return DeclarationName(); + + return Context.DeclarationNames.getCXXConversionFunctionName( + Context.getCanonicalType(Ty)); + } + + case UnqualifiedId::IK_ConstructorName: { + QualType Ty = GetTypeFromParser(Name.ConstructorName); + if (Ty.isNull()) + return DeclarationName(); + + return Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(Ty)); + } + + case UnqualifiedId::IK_DestructorName: { + QualType Ty = GetTypeFromParser(Name.DestructorName); + if (Ty.isNull()) + return DeclarationName(); + + return Context.DeclarationNames.getCXXDestructorName( + Context.getCanonicalType(Ty)); + } + + case UnqualifiedId::IK_TemplateId: { + TemplateName TName + = TemplateName::getFromVoidPointer(Name.TemplateId->Template); + if (TemplateDecl *Template = TName.getAsTemplateDecl()) + return Template->getDeclName(); + if (OverloadedFunctionDecl *Ovl = TName.getAsOverloadedFunctionDecl()) + return Ovl->getDeclName(); + + return DeclarationName(); + } } - + assert(false && "Unknown name kind"); - return DeclarationName(); + return DeclarationName(); } /// isNearlyMatchingFunction - Determine whether the C++ functions @@ -1986,12 +2000,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); - TypedefDecl *NewTD = ParseTypedefDecl(S, D, R); + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, DInfo); if (!NewTD) return 0; - if (D.isInvalidType()) - NewTD->setInvalidDecl(); - // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); // Merge the decl with the existing one if appropriate. If the decl is @@ -2013,7 +2024,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative); if (!FixedTy.isNull()) { Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); - NewTD->setUnderlyingType(FixedTy); + NewTD->setTypeDeclaratorInfo(Context.getTrivialDeclaratorInfo(FixedTy)); } else { if (SizeIsNegative) Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); @@ -2516,7 +2527,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, isInline |= IsFunctionDefinition; } - if (D.getKind() == Declarator::DK_Constructor) { + if (Name.getNameKind() == DeclarationName::CXXConstructorName) { // This is a C++ constructor declaration. assert(DC->isRecord() && "Constructors can only be declared in a member context"); @@ -2529,7 +2540,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, D.getIdentifierLoc(), Name, R, DInfo, isExplicit, isInline, /*isImplicitlyDeclared=*/false); - } else if (D.getKind() == Declarator::DK_Destructor) { + } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { R = CheckDestructorDeclarator(D, SC); @@ -2551,7 +2562,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /*hasPrototype=*/true); D.setInvalidType(); } - } else if (D.getKind() == Declarator::DK_Conversion) { + } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { if (!DC->isRecord()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member); @@ -2795,10 +2806,10 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (D.getKind() == Declarator::DK_TemplateId) { - TemplateIdAnnotation *TemplateId = D.getTemplateId(); + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->getTemplateArgIsType(), @@ -3101,7 +3112,7 @@ void Sema::CheckMain(FunctionDecl* FD) { // C99 6.7.4p4: In a hosted environment, the inline function specifier // shall not appear in a declaration of main. // static main is not an error under C99, but we should warn about it. - bool isInline = FD->isInline(); + bool isInline = FD->isInlineSpecified(); bool isStatic = FD->getStorageClass() == FunctionDecl::Static; if (isInline || isStatic) { unsigned diagID = diag::warn_unusual_main_decl; @@ -3442,7 +3453,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, if (getLangOptions().CPlusPlus) { QualType InitType = Type; if (const ArrayType *Array = Context.getAsArrayType(Type)) - InitType = Array->getElementType(); + InitType = Context.getBaseElementType(Array); if ((!Var->hasExternalStorage() && !Var->isExternC()) && InitType->isRecordType() && !InitType->isDependentType()) { if (!RequireCompleteType(Var->getLocation(), InitType, @@ -3465,7 +3476,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, else { // FIXME: Cope with initialization of arrays if (!Constructor->isTrivial() && - InitializeVarWithConstructor(Var, Constructor, InitType, + InitializeVarWithConstructor(Var, Constructor, move_arg(ConstructorArgs))) Var->setInvalidDecl(); @@ -3626,8 +3637,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { DeclaratorInfo *DInfo = 0; TagDecl *OwnedDecl = 0; - QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, - &OwnedDecl); + QualType parmDeclType = GetTypeForDeclarator(D, S, &DInfo, &OwnedDecl); if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { // C++ [dcl.fct]p6: @@ -3668,16 +3678,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { QualType T = adjustParameterType(parmDeclType); - ParmVarDecl *New; - if (T == parmDeclType) // parameter type did not need adjustment - New = ParmVarDecl::Create(Context, CurContext, - D.getIdentifierLoc(), II, - parmDeclType, DInfo, StorageClass, - 0); - else // keep track of both the adjusted and unadjusted types - New = OriginalParmVarDecl::Create(Context, CurContext, - D.getIdentifierLoc(), II, T, DInfo, - parmDeclType, StorageClass, 0); + ParmVarDecl *New + = ParmVarDecl::Create(Context, CurContext, D.getIdentifierLoc(), II, + T, DInfo, StorageClass, 0); if (D.isInvalidType()) New->setInvalidDecl(); @@ -3776,6 +3779,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, } Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { + // Clear the last template instantiation error context. + LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation(); + if (!D) return D; FunctionDecl *FD = 0; @@ -4104,15 +4110,21 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } } -TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T) { +TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, + DeclaratorInfo *DInfo) { assert(D.getIdentifier() && "Wrong callback for declspec without declarator"); assert(!T.isNull() && "GetTypeForDeclarator() returned null type"); + if (!DInfo) { + assert(D.isInvalidType() && "no declarator info for valid type"); + DInfo = Context.getTrivialDeclaratorInfo(T); + } + // Scope manipulation handled by caller. TypedefDecl *NewTD = TypedefDecl::Create(Context, CurContext, D.getIdentifierLoc(), D.getIdentifier(), - T); + DInfo); if (const TagType *TT = T->getAs<TagType>()) { TagDecl *TD = TT->getDecl(); @@ -4321,9 +4333,6 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } if (PrevDecl) { - // Check whether the previous declaration is usable. - (void)DiagnoseUseOfDecl(PrevDecl, NameLoc); - if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared // in the same scope (so that the definition/declaration completes or @@ -4955,12 +4964,16 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { case CXXDefaultConstructor: if (RD->hasUserDeclaredConstructor()) { typedef CXXRecordDecl::ctor_iterator ctor_iter; - for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce; ++ci) - if (!ci->isImplicitlyDefined(Context)) { + for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){ + const FunctionDecl *body = 0; + ci->getBody(body); + if (!body || + !cast<CXXConstructorDecl>(body)->isImplicitlyDefined(Context)) { SourceLocation CtorLoc = ci->getLocation(); Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; return; } + } assert(0 && "found no user-declared constructors"); return; @@ -5038,7 +5051,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { // Check for nontrivial bases (and recurse). for (base_iter bi = RD->bases_begin(), be = RD->bases_end(); bi != be; ++bi) { const RecordType *BaseRT = bi->getType()->getAs<RecordType>(); - assert(BaseRT); + assert(BaseRT && "Don't know how to handle dependent bases"); CXXRecordDecl *BaseRecTy = cast<CXXRecordDecl>(BaseRT->getDecl()); if (!(BaseRecTy->*hasTrivial)()) { SourceLocation BaseLoc = bi->getSourceRange().getBegin(); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 341d49e..18f57da 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -193,7 +193,8 @@ static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, // This will run the reguired checks. QualType T = S.BuildExtVectorType(curType, S.Owned(sizeExpr), Attr.getLoc()); if (!T.isNull()) { - tDecl->setUnderlyingType(T); + // FIXME: preserve the old source info. + tDecl->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(T)); // Remember this typedef decl, we will need it later for diagnostics. S.ExtVectorDecls.push_back(tDecl); @@ -278,8 +279,11 @@ static void HandleVectorSizeAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) VD->setType(CurType); - else - cast<TypedefDecl>(D)->setUnderlyingType(CurType); + else { + // FIXME: preserve existing source info. + DeclaratorInfo *DInfo = S.Context.getTrivialDeclaratorInfo(CurType); + cast<TypedefDecl>(D)->setTypeDeclaratorInfo(DInfo); + } } static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -897,7 +901,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Currently, the dllimport attribute is ignored for inlined functions. // Warning is emitted. - if (FD->isInline()) { + if (FD->isInlineSpecified()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } @@ -942,7 +946,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Currently, the dllexport attribute is ignored for inlined functions, unless // the -fkeep-inline-functions flag has been used. Warning is emitted; - if (FD->isInline()) { + if (FD->isInlineSpecified()) { // FIXME: ... unless the -fkeep-inline-functions flag has been used. S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllexport"; return; @@ -1028,6 +1032,22 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) StdCallAttr()); } +/// Diagnose the use of a non-standard calling convention on the given +/// function. +static void DiagnoseCConv(FunctionDecl *D, const char *CConv, + SourceLocation Loc, Sema &S) { + if (!D->hasPrototype()) { + S.Diag(Loc, diag::err_cconv_knr) << CConv; + return; + } + + const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>(); + if (T->isVariadic()) { + S.Diag(Loc, diag::err_cconv_varargs) << CConv; + return; + } +} + static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { // Attribute has no arguments. if (Attr.getNumArgs() != 0) { @@ -1041,6 +1061,8 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } + DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S); + // stdcall and fastcall attributes are mutually incompatible. if (d->getAttr<StdCallAttr>()) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) @@ -1636,9 +1658,10 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } // Install the new type. - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) - TD->setUnderlyingType(NewTy); - else + if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + // FIXME: preserve existing source info. + TD->setTypeDeclaratorInfo(S.Context.getTrivialDeclaratorInfo(NewTy)); + } else cast<ValueDecl>(D)->setType(NewTy); } @@ -1688,7 +1711,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - if (!Fn->isInline()) { + if (!Fn->isInlineSpecified()) { S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline); return; } @@ -1944,3 +1967,62 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { if (const AttributeList *Attrs = PD.getAttributes()) ProcessDeclAttributeList(S, D, Attrs); } + +/// PushParsingDeclaration - Enter a new "scope" of deprecation +/// warnings. +/// +/// The state token we use is the start index of this scope +/// on the warning stack. +Action::ParsingDeclStackState Sema::PushParsingDeclaration() { + ParsingDeclDepth++; + return (ParsingDeclStackState) DelayedDeprecationWarnings.size(); +} + +static bool isDeclDeprecated(Decl *D) { + do { + if (D->hasAttr<DeprecatedAttr>()) + return true; + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} + +void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) { + assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack"); + ParsingDeclDepth--; + + if (DelayedDeprecationWarnings.empty()) + return; + + unsigned SavedIndex = (unsigned) S; + assert(SavedIndex <= DelayedDeprecationWarnings.size() && + "saved index is out of bounds"); + + if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) { + for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) { + SourceLocation Loc = DelayedDeprecationWarnings[I].first; + NamedDecl *&ND = DelayedDeprecationWarnings[I].second; + if (ND) { + Diag(Loc, diag::warn_deprecated) << ND->getDeclName(); + + // Prevent this from triggering multiple times. + ND = 0; + } + } + } + + DelayedDeprecationWarnings.set_size(SavedIndex); +} + +void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) { + // Delay if we're currently parsing a declaration. + if (ParsingDeclDepth) { + DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D)); + return; + } + + // Otherwise, don't warn if our current context is deprecated. + if (isDeclDeprecated(cast<Decl>(CurContext))) + return; + + Diag(Loc, diag::warn_deprecated) << D->getDeclName(); +} diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6d1f4ea..bc25513 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1123,7 +1123,7 @@ Sema::BuildBaseInitializer(QualType BaseType, Expr **Args, } void -Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, +Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers, llvm::SmallVectorImpl<CXXBaseSpecifier *>& Bases, @@ -1179,7 +1179,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); AllToInit.push_back(Value); @@ -1187,18 +1187,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, else { CXXRecordDecl *VBaseDecl = cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - assert(VBaseDecl && "setBaseOrMemberInitializers - VBaseDecl null"); + assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null"); CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context); - if (!Ctor) + if (!Ctor) { Bases.push_back(VBase); - else - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + continue; + } + ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); + if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), + Constructor->getLocation(), CtorArgs)) + continue; + + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + CXXBaseOrMemberInitializer *Member = - new (Context) CXXBaseOrMemberInitializer(VBase->getType(), 0, 0, - Ctor, - SourceLocation(), - SourceLocation()); + new (Context) CXXBaseOrMemberInitializer(VBase->getType(), + CtorArgs.takeAs<Expr>(), + CtorArgs.size(), Ctor, + SourceLocation(), + SourceLocation()); AllToInit.push_back(Member); } } @@ -1216,7 +1224,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); if (CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context)) MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); AllToInit.push_back(Value); @@ -1224,18 +1232,26 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, else { CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "setBaseOrMemberInitializers - BaseDecl null"); + assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context); - if (!Ctor) + if (!Ctor) { Bases.push_back(Base); - else - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); + continue; + } + + ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); + if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), + Constructor->getLocation(), CtorArgs)) + continue; + + MarkDeclarationReferenced(Constructor->getLocation(), Ctor); CXXBaseOrMemberInitializer *Member = - new (Context) CXXBaseOrMemberInitializer(Base->getType(), 0, 0, - BaseDecl->getDefaultConstructor(Context), - SourceLocation(), - SourceLocation()); + new (Context) CXXBaseOrMemberInitializer(Base->getType(), + CtorArgs.takeAs<Expr>(), + CtorArgs.size(), Ctor, + SourceLocation(), + SourceLocation()); AllToInit.push_back(Member); } } @@ -1268,7 +1284,7 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, QualType FT = (*Field)->getType(); if (const RecordType* RT = FT->getAs<RecordType>()) { CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RT->getDecl()); - assert(FieldRecDecl && "setBaseOrMemberInitializers - BaseDecl null"); + assert(FieldRecDecl && "SetBaseOrMemberInitializers - BaseDecl null"); if (CXXConstructorDecl *Ctor = FieldRecDecl->getDefaultConstructor(Context)) MarkDeclarationReferenced(Value->getSourceLocation(), Ctor); @@ -1281,13 +1297,22 @@ Sema::setBaseOrMemberInitializers(CXXConstructorDecl *Constructor, if (const RecordType* RT = FT->getAs<RecordType>()) { CXXConstructorDecl *Ctor = cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context); - if (!Ctor && !FT->isDependentType()) + if (!Ctor && !FT->isDependentType()) { Fields.push_back(*Field); + continue; + } + + ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); + if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), + Constructor->getLocation(), CtorArgs)) + continue; + CXXBaseOrMemberInitializer *Member = - new (Context) CXXBaseOrMemberInitializer((*Field), 0, 0, - Ctor, - SourceLocation(), - SourceLocation()); + new (Context) CXXBaseOrMemberInitializer(*Field,CtorArgs.takeAs<Expr>(), + CtorArgs.size(), Ctor, + SourceLocation(), + SourceLocation()); + AllToInit.push_back(Member); if (Ctor) MarkDeclarationReferenced(Constructor->getLocation(), Ctor); @@ -1327,10 +1352,10 @@ Sema::BuildBaseOrMemberInitializers(ASTContext &C, CXXBaseOrMemberInitializer **Initializers, unsigned NumInitializers ) { - llvm::SmallVector<CXXBaseSpecifier *, 4>Bases; - llvm::SmallVector<FieldDecl *, 4>Members; + llvm::SmallVector<CXXBaseSpecifier *, 4> Bases; + llvm::SmallVector<FieldDecl *, 4> Members; - setBaseOrMemberInitializers(Constructor, + SetBaseOrMemberInitializers(Constructor, Initializers, NumInitializers, Bases, Members); for (unsigned int i = 0; i < Bases.size(); i++) Diag(Bases[i]->getSourceRange().getBegin(), @@ -1976,6 +2001,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // and for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) { + assert(!Base->getType()->isDependentType() && + "Cannot generate implicit members for class with dependent bases."); const CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); const CXXMethodDecl *MD = 0; @@ -2268,7 +2295,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // (7.1.3); however, a typedef-name that names a class shall not // be used as the identifier in the declarator for a destructor // declaration. - QualType DeclaratorType = GetTypeFromParser(D.getDeclaratorIdType()); + QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); if (isa<TypedefType>(DeclaratorType)) { Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType; @@ -2394,7 +2421,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // C++ [class.conv.fct]p4: // The conversion-type-id shall not represent a function type nor // an array type. - QualType ConvType = GetTypeFromParser(D.getDeclaratorIdType()); + QualType ConvType = GetTypeFromParser(D.getName().ConversionFunctionId); if (ConvType->isArrayType()) { Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); ConvType = Context.getPointerType(ConvType); @@ -3152,10 +3179,9 @@ Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor, bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, - QualType DeclInitType, MultiExprArg Exprs) { OwningExprResult TempResult = - BuildCXXConstructExpr(VD->getLocation(), DeclInitType, Constructor, + BuildCXXConstructExpr(VD->getLocation(), VD->getType(), Constructor, move(Exprs)); if (TempResult.isInvalid()) return true; @@ -3235,7 +3261,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // class type. QualType DeclInitType = VDecl->getType(); if (const ArrayType *Array = Context.getAsArrayType(DeclInitType)) - DeclInitType = Array->getElementType(); + DeclInitType = Context.getBaseElementType(Array); // FIXME: This isn't the right place to complete the type. if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(), @@ -3260,7 +3286,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, RealDecl->setInvalidDecl(); else { VDecl->setCXXDirectInitializer(true); - if (InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, + if (InitializeVarWithConstructor(VDecl, Constructor, move_arg(ConstructorArgs))) RealDecl->setInvalidDecl(); FinalizeVarWithDestructor(VDecl, DeclInitType); @@ -4269,8 +4295,7 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, /// We permit this as a special case; if there are any template /// parameters present at all, require proper matching, i.e. /// template <> template <class T> friend class A<int>::B; -Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, - const DeclSpec &DS, +Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, MultiTemplateParamsArg TempParams) { SourceLocation Loc = DS.getSourceRange().getBegin(); @@ -4280,9 +4305,10 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, // Try to convert the decl specifier to a type. This works for // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. - bool invalid = false; - QualType T = ConvertDeclSpecToType(DS, Loc, invalid); - if (invalid) return DeclPtrTy(); + Declarator TheDeclarator(DS, Declarator::MemberContext); + QualType T = GetTypeForDeclarator(TheDeclarator, S); + if (TheDeclarator.isInvalidType()) + return DeclPtrTy(); // This is definitely an error in C++98. It's probably meant to // be forbidden in C++0x, too, but the specification is just @@ -4489,12 +4515,12 @@ Sema::ActOnFriendFunctionDecl(Scope *S, if (DC->isFileContext()) { // This implies that it has to be an operator or function. - if (D.getKind() == Declarator::DK_Constructor || - D.getKind() == Declarator::DK_Destructor || - D.getKind() == Declarator::DK_Conversion) { + if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || + D.getName().getKind() == UnqualifiedId::IK_DestructorName || + D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { Diag(Loc, diag::err_introducing_special_friend) << - (D.getKind() == Declarator::DK_Constructor ? 0 : - D.getKind() == Declarator::DK_Destructor ? 1 : 2); + (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : + D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); return DeclPtrTy(); } } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 22a5179..93f8d0d 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1707,29 +1707,22 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( llvm::SmallVector<ParmVarDecl*, 16> Params; for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) { - QualType ArgType, UnpromotedArgType; + QualType ArgType; + DeclaratorInfo *DI; if (ArgInfo[i].Type == 0) { - UnpromotedArgType = ArgType = Context.getObjCIdType(); + ArgType = Context.getObjCIdType(); + DI = 0; } else { - UnpromotedArgType = ArgType = GetTypeFromParser(ArgInfo[i].Type); + ArgType = GetTypeFromParser(ArgInfo[i].Type, &DI); // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). ArgType = adjustParameterType(ArgType); } - ParmVarDecl* Param; - if (ArgType == UnpromotedArgType) - Param = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, - ArgInfo[i].Name, ArgType, - /*DInfo=*/0, //FIXME: Pass info here. - VarDecl::None, 0); - else - Param = OriginalParmVarDecl::Create(Context, ObjCMethod, - ArgInfo[i].NameLoc, - ArgInfo[i].Name, ArgType, - /*DInfo=*/0, //FIXME: Pass info here. - UnpromotedArgType, - VarDecl::None, 0); + ParmVarDecl* Param + = ParmVarDecl::Create(Context, ObjCMethod, ArgInfo[i].NameLoc, + ArgInfo[i].Name, ArgType, DI, + VarDecl::None, 0); if (ArgType->isObjCInterfaceType()) { Diag(ArgInfo[i].NameLoc, @@ -1755,6 +1748,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( if (AttrList) ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + const ObjCMethodDecl *InterfaceMD = 0; + // For implementations (which can be very "coarse grain"), we add the // method now. This allows the AST to implement lookup methods that work // incrementally (without waiting until we parse the @end). It also allows @@ -1768,6 +1763,8 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( PrevMethod = ImpDecl->getClassMethod(Sel); ImpDecl->addClassMethod(ObjCMethod); } + InterfaceMD = ImpDecl->getClassInterface()->getMethod(Sel, + MethodType == tok::minus); if (AttrList) Diag(EndLoc, diag::warn_attribute_method_def); } else if (ObjCCategoryImplDecl *CatImpDecl = @@ -1788,6 +1785,12 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( << ObjCMethod->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } + + // If the interface declared this method, and it was deprecated there, + // mark it deprecated here. + if (InterfaceMD && InterfaceMD->hasAttr<DeprecatedAttr>()) + ObjCMethod->addAttr(::new (Context) DeprecatedAttr()); + return DeclPtrTy::make(ObjCMethod); } @@ -1900,33 +1903,34 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // handling. if ((CCPrimary = CDecl->getClassInterface())) { // Find the property in continuation class's primary class only. - ObjCPropertyDecl *PIDecl = 0; IdentifierInfo *PropertyId = FD.D.getIdentifier(); - for (ObjCInterfaceDecl::prop_iterator - I = CCPrimary->prop_begin(), E = CCPrimary->prop_end(); - I != E; ++I) - if ((*I)->getIdentifier() == PropertyId) { - PIDecl = *I; - break; - } - - if (PIDecl) { + if (ObjCPropertyDecl *PIDecl = + CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) { // property 'PIDecl's readonly attribute will be over-ridden // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributes(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { - if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) != - (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic)) + unsigned assignRetainCopyNonatomic = + (ObjCPropertyDecl::OBJC_PR_assign | + ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_nonatomic); + if ((Attributes & assignRetainCopyNonatomic) != + (PIkind & assignRetainCopyNonatomic)) { Diag(AtLoc, diag::warn_property_attr_mismatch); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } PIDecl->makeitReadWriteAttribute(); if (Attributes & ObjCDeclSpec::DQ_PR_retain) PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); if (Attributes & ObjCDeclSpec::DQ_PR_copy) PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); PIDecl->setSetterName(SetterSel); - } else + } else { Diag(AtLoc, diag::err_use_continuation_class) << CCPrimary->getDeclName(); + Diag(PIDecl->getLocation(), diag::note_property_declare); + } *isOverridingProperty = true; // Make sure setter decl is synthesized, and added to primary // class's list. @@ -2054,6 +2058,14 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); return DeclPtrTy(); } + if (const ObjCCategoryDecl *CD = + dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { + if (CD->getIdentifier()) { + Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); + Diag(property->getLocation(), diag::note_property_declare); + return DeclPtrTy(); + } + } } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { if (Synthesize) { Diag(AtLoc, diag::error_synthesize_category_decl); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index ae45429..ac7cced 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -37,40 +37,24 @@ using namespace clang; /// used, or produce an error (and return true) if a C++0x deleted /// function is being used. /// +/// If IgnoreDeprecated is set to true, this should not want about deprecated +/// decls. +/// /// \returns true if there was an error (this declaration cannot be /// referenced), false otherwise. +/// bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. if (D->getAttr<DeprecatedAttr>()) { - // Implementing deprecated stuff requires referencing deprecated - // stuff. Don't warn if we are implementing a deprecated - // construct. - bool isSilenced = false; - - if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { - // If this reference happens *in* a deprecated function or method, don't - // warn. - isSilenced = ND->getAttr<DeprecatedAttr>(); - - // If this is an Objective-C method implementation, check to see if the - // method was deprecated on the declaration, not the definition. - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND)) { - // The semantic decl context of a ObjCMethodDecl is the - // ObjCImplementationDecl. - if (ObjCImplementationDecl *Impl - = dyn_cast<ObjCImplementationDecl>(MD->getParent())) { - - MD = Impl->getClassInterface()->getMethod(MD->getSelector(), - MD->isInstanceMethod()); - isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); - } - } - } - - if (!isSilenced) - Diag(Loc, diag::warn_deprecated) << D->getDeclName(); + EmitDeprecationWarning(D, Loc); } + // See if the decl is unavailable + if (D->getAttr<UnavailableAttr>()) { + Diag(Loc, diag::warn_unavailable) << D->getDeclName(); + Diag(D->getLocation(), diag::note_unavailable_here) << 0; + } + // See if this is a deleted function. if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->isDeleted()) { @@ -80,12 +64,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { } } - // See if the decl is unavailable - if (D->getAttr<UnavailableAttr>()) { - Diag(Loc, diag::warn_unavailable) << D->getDeclName(); - Diag(D->getLocation(), diag::note_unavailable_here) << 0; - } - return false; } @@ -432,23 +410,7 @@ static bool ShouldSnapshotBlockValueReference(BlockSemaInfo *CurBlock, -/// ActOnIdentifierExpr - The parser read an identifier in expression context, -/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this -/// identifier is used in a function call context. -/// SS is only used for a C++ qualified-id (foo::bar) to indicate the -/// class or namespace that the identifier must be a member of. -Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc, - IdentifierInfo &II, - bool HasTrailingLParen, - const CXXScopeSpec *SS, - bool isAddressOfOperand) { - return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS, - isAddressOfOperand); -} - -/// BuildDeclRefExpr - Build either a DeclRefExpr or a -/// QualifiedDeclRefExpr based on whether or not SS is a -/// nested-name-specifier. +/// BuildDeclRefExpr - Build a DeclRefExpr. Sema::OwningExprResult Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, bool TypeDependent, bool ValueDependent, @@ -476,15 +438,11 @@ Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc, MarkDeclarationReferenced(Loc, D); - Expr *E; - if (SS && !SS->isEmpty()) { - E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, - ValueDependent, SS->getRange(), - static_cast<NestedNameSpecifier *>(SS->getScopeRep())); - } else - E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent); - - return Owned(E); + return Owned(DeclRefExpr::Create(Context, + SS? (NestedNameSpecifier *)SS->getScopeRep() : 0, + SS? SS->getRange() : SourceRange(), + D, Loc, + Ty, TypeDependent, ValueDependent)); } /// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or @@ -656,15 +614,43 @@ Sema::BuildAnonymousStructUnionMemberReference(SourceLocation Loc, return Owned(Result); } +Sema::OwningExprResult Sema::ActOnIdExpression(Scope *S, + const CXXScopeSpec &SS, + UnqualifiedId &Name, + bool HasTrailingLParen, + bool IsAddressOfOperand) { + if (Name.getKind() == UnqualifiedId::IK_TemplateId) { + ASTTemplateArgsPtr TemplateArgsPtr(*this, + Name.TemplateId->getTemplateArgs(), + Name.TemplateId->getTemplateArgIsType(), + Name.TemplateId->NumArgs); + return ActOnTemplateIdExpr(SS, + TemplateTy::make(Name.TemplateId->Template), + Name.TemplateId->TemplateNameLoc, + Name.TemplateId->LAngleLoc, + TemplateArgsPtr, + Name.TemplateId->getTemplateArgLocations(), + Name.TemplateId->RAngleLoc); + } + + // FIXME: We lose a bunch of source information by doing this. Later, + // we'll want to merge ActOnDeclarationNameExpr's logic into + // ActOnIdExpression. + return ActOnDeclarationNameExpr(S, + Name.StartLocation, + GetNameFromUnqualifiedId(Name), + HasTrailingLParen, + &SS, + IsAddressOfOperand); +} + /// ActOnDeclarationNameExpr - The parser has read some kind of name /// (e.g., a C++ id-expression (C++ [expr.prim]p1)). This routine /// performs lookup on that name and returns an expression that refers /// to that name. This routine isn't directly called from the parser, /// because the parser doesn't know about DeclarationName. Rather, -/// this routine is called by ActOnIdentifierExpr, -/// ActOnOperatorFunctionIdExpr, and ActOnConversionFunctionExpr, -/// which form the DeclarationName from the corresponding syntactic -/// forms. +/// this routine is called by ActOnIdExpression, which contains a +/// parsed UnqualifiedId. /// /// HasTrailingLParen indicates whether this identifier is used in a /// function call context. LookupCtx is only used for a C++ @@ -745,8 +731,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // FIXME: This should use a new expr for a direct reference, don't // turn this into Self->ivar, just return a BareIVarExpr or something. IdentifierInfo &II = Context.Idents.get("self"); - OwningExprResult SelfExpr = ActOnIdentifierExpr(S, SourceLocation(), - II, false); + UnqualifiedId SelfName; + SelfName.setIdentifier(&II, SourceLocation()); + CXXScopeSpec SelfScopeSpec; + OwningExprResult SelfExpr = ActOnIdExpression(S, SelfScopeSpec, + SelfName, false, false); MarkDeclarationReferenced(Loc, IV); return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(), Loc, @@ -1083,7 +1072,8 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, // - a constant with integral or enumeration type and is // initialized with an expression that is value-dependent else if (const VarDecl *Dcl = dyn_cast<VarDecl>(VD)) { - if (Dcl->getType().getCVRQualifiers() == Qualifiers::Const && + if (Context.getCanonicalType(Dcl->getType()).getCVRQualifiers() + == Qualifiers::Const && Dcl->getInit()) { ValueDependent = Dcl->getInit()->isValueDependent(); } @@ -1300,7 +1290,7 @@ bool Sema::CheckSizeOfAlignOfOperand(QualType exprType, return false; // C99 6.5.3.4p1: - if (isa<FunctionType>(exprType)) { + if (exprType->isFunctionType()) { // alignof(function) is allowed as an extension. if (isSizeof) Diag(OpLoc, diag::ext_sizeof_function_type) << ExprRange; @@ -1358,17 +1348,20 @@ bool Sema::CheckAlignOfExpr(Expr *E, SourceLocation OpLoc, /// \brief Build a sizeof or alignof expression given a type operand. Action::OwningExprResult -Sema::CreateSizeOfAlignOfExpr(QualType T, SourceLocation OpLoc, +Sema::CreateSizeOfAlignOfExpr(DeclaratorInfo *DInfo, + SourceLocation OpLoc, bool isSizeOf, SourceRange R) { - if (T.isNull()) + if (!DInfo) return ExprError(); + QualType T = DInfo->getType(); + if (!T->isDependentType() && CheckSizeOfAlignOfOperand(T, OpLoc, R, isSizeOf)) return ExprError(); // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t. - return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, T, + return Owned(new (Context) SizeOfAlignOfExpr(isSizeOf, DInfo, Context.getSizeType(), OpLoc, R.getEnd())); } @@ -1410,12 +1403,11 @@ Sema::ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, if (TyOrEx == 0) return ExprError(); if (isType) { - // FIXME: Preserve type source info. - QualType ArgTy = GetTypeFromParser(TyOrEx); - return CreateSizeOfAlignOfExpr(ArgTy, OpLoc, isSizeof, ArgRange); + DeclaratorInfo *DInfo; + (void) GetTypeFromParser(TyOrEx, &DInfo); + return CreateSizeOfAlignOfExpr(DInfo, OpLoc, isSizeof, ArgRange); } - // Get the end location. Expr *ArgEx = (Expr *)TyOrEx; Action::OwningExprResult Result = CreateSizeOfAlignOfExpr(ArgEx, OpLoc, isSizeof, ArgEx->getSourceRange()); @@ -1602,103 +1594,18 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, LHSExp->getType()->isEnumeralType() || RHSExp->getType()->isRecordType() || RHSExp->getType()->isEnumeralType())) { - // Add the appropriate overloaded operators (C++ [over.match.oper]) - // to the candidate set. - OverloadCandidateSet CandidateSet; - Expr *Args[2] = { LHSExp, RHSExp }; - AddOperatorCandidates(OO_Subscript, S, LLoc, Args, 2, CandidateSet, - SourceRange(LLoc, RLoc)); - - // Perform overload resolution. - OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, LLoc, Best)) { - case OR_Success: { - // We found a built-in operator or an overloaded operator. - FunctionDecl *FnDecl = Best->Function; - - if (FnDecl) { - // We matched an overloaded operator. Build a call to that - // operator. - - // Convert the arguments. - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { - if (PerformObjectArgumentInitialization(LHSExp, Method) || - PerformCopyInitialization(RHSExp, - FnDecl->getParamDecl(0)->getType(), - "passing")) - return ExprError(); - } else { - // Convert the arguments. - if (PerformCopyInitialization(LHSExp, - FnDecl->getParamDecl(0)->getType(), - "passing") || - PerformCopyInitialization(RHSExp, - FnDecl->getParamDecl(1)->getType(), - "passing")) - return ExprError(); - } - - // Determine the result type - QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); - - // Build the actual expression node. - Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), - SourceLocation()); - UsualUnaryConversions(FnExpr); - - Base.release(); - Idx.release(); - Args[0] = LHSExp; - Args[1] = RHSExp; - - ExprOwningPtr<CXXOperatorCallExpr> - TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript, - FnExpr, Args, 2, - ResultTy, RLoc)); - if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(), - FnDecl)) - return ExprError(); - - return Owned(TheCall.release()); - } else { - // We matched a built-in operator. Convert the arguments, then - // break out so that we will build the appropriate built-in - // operator node. - if (PerformCopyInitialization(LHSExp, Best->BuiltinTypes.ParamTypes[0], - "passing") || - PerformCopyInitialization(RHSExp, Best->BuiltinTypes.ParamTypes[1], - "passing")) - return ExprError(); - - break; - } - } - - case OR_No_Viable_Function: - // No viable function; fall through to handling this as a - // built-in operator, which will produce an error message for us. - break; + return CreateOverloadedArraySubscriptExpr(LLoc, RLoc, move(Base),move(Idx)); + } - case OR_Ambiguous: - Diag(LLoc, diag::err_ovl_ambiguous_oper) - << "[]" - << LHSExp->getSourceRange() << RHSExp->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); - return ExprError(); + return CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc); +} - case OR_Deleted: - Diag(LLoc, diag::err_ovl_deleted_oper) - << Best->Function->isDeleted() - << "[]" - << LHSExp->getSourceRange() << RHSExp->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); - return ExprError(); - } - // Either we found no viable overloaded operator or we matched a - // built-in operator. In either case, fall through to trying to - // build a built-in operation. - } +Action::OwningExprResult +Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, + ExprArg Idx, SourceLocation RLoc) { + Expr *LHSExp = static_cast<Expr*>(Base.get()); + Expr *RHSExp = static_cast<Expr*>(Idx.get()); // Perform default conversions. DefaultFunctionArrayConversion(LHSExp); @@ -1961,7 +1868,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, DeclarationName MemberName, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS, @@ -2549,13 +2456,77 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, return ExprError(); } -Action::OwningExprResult -Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, - tok::TokenKind OpKind, SourceLocation MemberLoc, - IdentifierInfo &Member, - DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS) { - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, MemberLoc, - DeclarationName(&Member), ObjCImpDecl, SS); +Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + UnqualifiedId &Member, + DeclPtrTy ObjCImpDecl, + bool HasTrailingLParen) { + if (Member.getKind() == UnqualifiedId::IK_TemplateId) { + TemplateName Template + = TemplateName::getFromVoidPointer(Member.TemplateId->Template); + + // FIXME: We're going to end up looking up the template based on its name, + // twice! + DeclarationName Name; + if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) + Name = ActualTemplate->getDeclName(); + else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl()) + Name = Ovl->getDeclName(); + else { + DependentTemplateName *DTN = Template.getAsDependentTemplateName(); + if (DTN->isIdentifier()) + Name = DTN->getIdentifier(); + else + Name = Context.DeclarationNames.getCXXOperatorName(DTN->getOperator()); + } + + // Translate the parser's template argument list in our AST format. + ASTTemplateArgsPtr TemplateArgsPtr(*this, + Member.TemplateId->getTemplateArgs(), + Member.TemplateId->getTemplateArgIsType(), + Member.TemplateId->NumArgs); + + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsPtr, + Member.TemplateId->getTemplateArgLocations(), + TemplateArgs); + TemplateArgsPtr.release(); + + // Do we have the save the actual template name? We might need it... + return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, + Member.TemplateId->TemplateNameLoc, + Name, true, Member.TemplateId->LAngleLoc, + TemplateArgs.data(), TemplateArgs.size(), + Member.TemplateId->RAngleLoc, DeclPtrTy(), + &SS); + } + + // FIXME: We lose a lot of source information by mapping directly to the + // DeclarationName. + OwningExprResult Result + = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, + Member.getSourceRange().getBegin(), + GetNameFromUnqualifiedId(Member), + ObjCImpDecl, &SS); + + if (Result.isInvalid() || HasTrailingLParen || + Member.getKind() != UnqualifiedId::IK_DestructorName) + return move(Result); + + // The only way a reference to a destructor can be used is to + // immediately call them. Since the next token is not a '(', produce a + // diagnostic and build the call now. + Expr *E = (Expr *)Result.get(); + SourceLocation ExpectedLParenLoc + = PP.getLocForEndOfToken(Member.getSourceRange().getEnd()); + Diag(E->getLocStart(), diag::err_dtor_expr_without_call) + << isa<CXXPseudoDestructorExpr>(E) + << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); + + return ActOnCallExpr(0, move(Result), ExpectedLParenLoc, + MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc); } Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -2713,7 +2684,7 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, SourceRange &QualifierRange, bool &ArgumentDependentLookup, bool &HasExplicitTemplateArguments, - const TemplateArgument *&ExplicitTemplateArgs, + const TemplateArgumentLoc *&ExplicitTemplateArgs, unsigned &NumExplicitTemplateArgs) { // Set defaults for all of the output parameters. Function = 0; @@ -2738,16 +2709,12 @@ void Sema::DeconstructCallFunction(Expr *FnExpr, cast<UnaryOperator>(FnExpr)->getOpcode() == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) { - // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). - ArgumentDependentLookup = false; - Qualifier = QDRExpr->getQualifier(); - QualifierRange = QDRExpr->getQualifierRange(); - Function = dyn_cast<NamedDecl>(QDRExpr->getDecl()); - break; } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { Function = dyn_cast<NamedDecl>(DRExpr->getDecl()); + if ((Qualifier = DRExpr->getQualifier())) { + ArgumentDependentLookup = false; + QualifierRange = DRExpr->getQualifierRange(); + } break; } else if (UnresolvedFunctionNameExpr *DepName = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { @@ -2866,24 +2833,29 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (BinaryOperator *BO = dyn_cast<BinaryOperator>(Fn->IgnoreParens())) { if (BO->getOpcode() == BinaryOperator::PtrMemD || BO->getOpcode() == BinaryOperator::PtrMemI) { - const FunctionProtoType *FPT = cast<FunctionProtoType>(BO->getType()); - QualType ResultTy = FPT->getResultType().getNonReferenceType(); + if (const FunctionProtoType *FPT = + dyn_cast<FunctionProtoType>(BO->getType())) { + QualType ResultTy = FPT->getResultType().getNonReferenceType(); - ExprOwningPtr<CXXMemberCallExpr> - TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, - NumArgs, ResultTy, - RParenLoc)); + ExprOwningPtr<CXXMemberCallExpr> + TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, + NumArgs, ResultTy, + RParenLoc)); - if (CheckCallReturnType(FPT->getResultType(), - BO->getRHS()->getSourceRange().getBegin(), - TheCall.get(), 0)) - return ExprError(); + if (CheckCallReturnType(FPT->getResultType(), + BO->getRHS()->getSourceRange().getBegin(), + TheCall.get(), 0)) + return ExprError(); - if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs, - RParenLoc)) - return ExprError(); + if (ConvertArgumentsForCall(&*TheCall, BO, 0, FPT, Args, NumArgs, + RParenLoc)) + return ExprError(); - return Owned(MaybeBindToTemporary(TheCall.release()).release()); + return Owned(MaybeBindToTemporary(TheCall.release()).release()); + } + return ExprError(Diag(Fn->getLocStart(), + diag::err_typecheck_call_not_function) + << Fn->getType() << Fn->getSourceRange()); } } } @@ -2893,7 +2865,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // lookup and whether there were any explicitly-specified template arguments. bool ADL = true; bool HasExplicitTemplateArgs = 0; - const TemplateArgument *ExplicitTemplateArgs = 0; + const TemplateArgumentLoc *ExplicitTemplateArgs = 0; unsigned NumExplicitTemplateArgs = 0; NestedNameSpecifier *Qualifier = 0; SourceRange QualifierRange; @@ -2932,19 +2904,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, if (!FDecl) return ExprError(); - // Update Fn to refer to the actual function selected. - Expr *NewFn = 0; - if (Qualifier) - NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), - Fn->getLocStart(), - false, false, - QualifierRange, - Qualifier); - else - NewFn = new (Context) DeclRefExpr(FDecl, FDecl->getType(), - Fn->getLocStart()); - Fn->Destroy(Context); - Fn = NewFn; + Fn = FixOverloadedFunctionReference(Fn, FDecl); } } @@ -3543,7 +3503,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, compositeType = Context.getObjCIdType(); } else if (LHSTy->isObjCIdType() || RHSTy->isObjCIdType()) { compositeType = Context.getObjCIdType(); - } else { + } else if (!(compositeType = + Context.areCommonBaseCompatible(LHSOPT, RHSOPT)).isNull()) + ; + else { Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); @@ -4080,7 +4043,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // This check seems unnatural, however it is necessary to ensure the proper // conversion of functions/arrays. If the conversion were done for all - // DeclExpr's (created by ActOnIdentifierExpr), it would mess up the unary + // DeclExpr's (created by ActOnIdExpression), it would mess up the unary // expressions that surpress this implicit conversion (&, sizeof). // // Suppress this for references: C++ 8.5.3p5. @@ -4428,6 +4391,10 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType()) return InvalidOperands(Loc, lex, rex); + // Vector shifts promote their scalar inputs to vector type. + if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) + return CheckVectorOperands(Loc, lex, rex); + // Shifts don't perform usual arithmetic conversions, they just do integer // promotions on each operand. C99 6.5.7p3 QualType LHSTy = Context.isPromotableBitField(lex); @@ -5083,7 +5050,6 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *Op, SourceLocation OpLoc, static NamedDecl *getPrimaryDecl(Expr *E) { switch (E->getStmtClass()) { case Stmt::DeclRefExprClass: - case Stmt::QualifiedDeclRefExprClass: return cast<DeclRefExpr>(E)->getDecl(); case Stmt::MemberExprClass: // If this is an arrow operator, the address is an offset from @@ -5199,7 +5165,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { // Okay: we can take the address of a field. // Could be a pointer to member, though, if there is an explicit // scope qualifier for the class. - if (isa<QualifiedDeclRefExpr>(op)) { + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier()) { DeclContext *Ctx = dcl->getDeclContext(); if (Ctx && Ctx->isRecord()) { if (FD->getType()->isReferenceType()) { @@ -5216,7 +5182,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(dcl)) { // Okay: we can take the address of a function. // As above. - if (isa<QualifiedDeclRefExpr>(op) && MD->isInstance()) + if (isa<DeclRefExpr>(op) && cast<DeclRefExpr>(op)->getQualifier() && + MD->isInstance()) return Context.getMemberPointerType(op->getType(), Context.getTypeDeclType(MD->getParent()).getTypePtr()); } else if (!isa<FunctionDecl>(dcl)) @@ -5426,6 +5393,72 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, OpLoc)); } +/// SuggestParentheses - Emit a diagnostic together with a fixit hint that wraps +/// ParenRange in parentheses. +static void SuggestParentheses(Sema &Self, SourceLocation Loc, + const PartialDiagnostic &PD, + SourceRange ParenRange) +{ + SourceLocation EndLoc = Self.PP.getLocForEndOfToken(ParenRange.getEnd()); + if (!ParenRange.getEnd().isFileID() || EndLoc.isInvalid()) { + // We can't display the parentheses, so just dig the + // warning/error and return. + Self.Diag(Loc, PD); + return; + } + + Self.Diag(Loc, PD) + << CodeModificationHint::CreateInsertion(ParenRange.getBegin(), "(") + << CodeModificationHint::CreateInsertion(EndLoc, ")"); +} + +/// DiagnoseBitwisePrecedence - Emit a warning when bitwise and comparison +/// operators are mixed in a way that suggests that the programmer forgot that +/// comparison operators have higher precedence. The most typical example of +/// such code is "flags & 0x0020 != 0", which is equivalent to "flags & 1". +static void DiagnoseBitwisePrecedence(Sema &Self, BinaryOperator::Opcode Opc, + SourceLocation OpLoc,Expr *lhs,Expr *rhs){ + typedef BinaryOperator BinOp; + BinOp::Opcode lhsopc = static_cast<BinOp::Opcode>(-1), + rhsopc = static_cast<BinOp::Opcode>(-1); + if (BinOp *BO = dyn_cast<BinOp>(lhs)) + lhsopc = BO->getOpcode(); + if (BinOp *BO = dyn_cast<BinOp>(rhs)) + rhsopc = BO->getOpcode(); + + // Subs are not binary operators. + if (lhsopc == -1 && rhsopc == -1) + return; + + // Bitwise operations are sometimes used as eager logical ops. + // Don't diagnose this. + if ((BinOp::isComparisonOp(lhsopc) || BinOp::isBitwiseOp(lhsopc)) && + (BinOp::isComparisonOp(rhsopc) || BinOp::isBitwiseOp(rhsopc))) + return; + + if (BinOp::isComparisonOp(lhsopc)) + SuggestParentheses(Self, OpLoc, + PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(lhs->getLocStart(), OpLoc) + << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(lhsopc), + SourceRange(cast<BinOp>(lhs)->getRHS()->getLocStart(), rhs->getLocEnd())); + else if (BinOp::isComparisonOp(rhsopc)) + SuggestParentheses(Self, OpLoc, + PDiag(diag::warn_precedence_bitwise_rel) + << SourceRange(OpLoc, rhs->getLocEnd()) + << BinOp::getOpcodeStr(Opc) << BinOp::getOpcodeStr(rhsopc), + SourceRange(lhs->getLocEnd(), cast<BinOp>(rhs)->getLHS()->getLocStart())); +} + +/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky +/// precedence. This currently diagnoses only "arg1 'bitwise' arg2 'eq' arg3". +/// But it could also warn about arg1 && arg2 || arg3, as GCC 4.3+ does. +static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperator::Opcode Opc, + SourceLocation OpLoc, Expr *lhs, Expr *rhs){ + if (BinaryOperator::isBitwiseOp(Opc)) + DiagnoseBitwisePrecedence(Self, Opc, OpLoc, lhs, rhs); +} + // Binary Operators. 'Tok' is the token for the operator. Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, @@ -5436,6 +5469,9 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, assert((lhs != 0) && "ActOnBinOp(): missing left expression"); assert((rhs != 0) && "ActOnBinOp(): missing right expression"); + // Emit warnings for tricky precedence issues, e.g. "bitfield & 0x4 == 0" + DiagnoseBinOpPrecedence(*this, Opc, TokLoc, lhs, rhs); + if (getLangOptions().CPlusPlus && (lhs->getType()->isOverloadableType() || rhs->getType()->isOverloadableType())) { @@ -5451,7 +5487,7 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, Expr *Args[2] = { lhs, rhs }; DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OverOp); - ArgumentDependentLookup(OpName, Args, 2, Functions); + ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions); } // Build the (potentially-overloaded, potentially-dependent) @@ -5569,7 +5605,7 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, Functions); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OverOp); - ArgumentDependentLookup(OpName, &Input, 1, Functions); + ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions); } return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input)); @@ -5673,6 +5709,10 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, if (!Dependent) { bool DidWarnAboutNonPOD = false; + if (RequireCompleteType(TypeLoc, Res->getType(), + diag::err_offsetof_incomplete_type)) + return ExprError(); + // FIXME: Dependent case loses a lot of information here. And probably // leaks like a sieve. for (unsigned i = 0; i != NumComponents; ++i) { @@ -6240,21 +6280,21 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // Implicit instantiation of function templates and member functions of // class templates. - if (!Function->getBody() && - Function->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) { + if (!Function->getBody() && Function->isImplicitlyInstantiable()) { bool AlreadyInstantiated = false; if (FunctionTemplateSpecializationInfo *SpecInfo = Function->getTemplateSpecializationInfo()) { if (SpecInfo->getPointOfInstantiation().isInvalid()) SpecInfo->setPointOfInstantiation(Loc); - else + else if (SpecInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) AlreadyInstantiated = true; } else if (MemberSpecializationInfo *MSInfo = Function->getMemberSpecializationInfo()) { if (MSInfo->getPointOfInstantiation().isInvalid()) MSInfo->setPointOfInstantiation(Loc); - else + else if (MSInfo->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) AlreadyInstantiated = true; } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d4d031f..4868c14 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -22,41 +22,6 @@ #include "llvm/ADT/STLExtras.h" using namespace clang; -/// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function -/// name (e.g., operator void const *) as an expression. This is -/// very similar to ActOnIdentifierExpr, except that instead of -/// providing an identifier the parser provides the type of the -/// conversion function. -Sema::OwningExprResult -Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc, - TypeTy *Ty, bool HasTrailingLParen, - const CXXScopeSpec &SS, - bool isAddressOfOperand) { - //FIXME: Preserve type source info. - QualType ConvType = GetTypeFromParser(Ty); - CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType); - DeclarationName ConvName - = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon); - return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen, - &SS, isAddressOfOperand); -} - -/// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator -/// name (e.g., @c operator+ ) as an expression. This is very -/// similar to ActOnIdentifierExpr, except that instead of providing -/// an identifier the parser provides the kind of overloaded -/// operator that was parsed. -Sema::OwningExprResult -Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc, - OverloadedOperatorKind Op, - bool HasTrailingLParen, - const CXXScopeSpec &SS, - bool isAddressOfOperand) { - DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op); - return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS, - isAddressOfOperand); -} - /// ActOnCXXTypeidOfType - Parse typeid( type-id ). Action::OwningExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, @@ -212,7 +177,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, PDiag(diag::err_invalid_incomplete_type_use) << FullRange)) return ExprError(); - + if (RequireNonAbstractType(TyBeginLoc, Ty, diag::err_allocation_of_abstract_type)) return ExprError(); @@ -288,7 +253,6 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, << FullRange); assert(NumExprs == 0 && "Expected 0 expressions"); - // C++ [expr.type.conv]p2: // The expression T(), where T is a simple-type-specifier for a non-array // complete object type or the (possibly cv-qualified) void type, creates an @@ -312,7 +276,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen) { Expr *ArraySize = 0; - unsigned Skip = 0; // If the specified type is an array, unwrap it and save the expression. if (D.getNumTypeObjects() > 0 && D.getTypeObject(0).Kind == DeclaratorChunk::Array) { @@ -323,14 +286,25 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, if (!Chunk.Arr.NumElts) return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) << D.getSourceRange()); + + if (ParenTypeId) { + // Can't have dynamic array size when the type-id is in parentheses. + Expr *NumElts = (Expr *)Chunk.Arr.NumElts; + if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() && + !NumElts->isIntegerConstantExpr(Context)) { + Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst) + << NumElts->getSourceRange(); + return ExprError(); + } + } + ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); - Skip = 1; + D.DropFirstTypeObject(); } // Every dimension shall be of constant size. - if (D.getNumTypeObjects() > 0 && - D.getTypeObject(0).Kind == DeclaratorChunk::Array) { - for (unsigned I = 1, N = D.getNumTypeObjects(); I < N; ++I) { + if (ArraySize) { + for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) { if (D.getTypeObject(I).Kind != DeclaratorChunk::Array) break; @@ -345,10 +319,10 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, } } } - + //FIXME: Store DeclaratorInfo in CXXNew expression. DeclaratorInfo *DInfo = 0; - QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo, Skip); + QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &DInfo); if (D.isInvalidType()) return ExprError(); @@ -935,7 +909,7 @@ Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc, // FIXME: Store DeclaratorInfo in the expression. DeclaratorInfo *DInfo = 0; TagDecl *OwnedTag = 0; - QualType Ty = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, &OwnedTag); + QualType Ty = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); if (Ty->isFunctionType()) { // The declarator shall not specify a function... // We exit without creating a CXXConditionDeclExpr because a FunctionDecl @@ -1139,6 +1113,10 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, From = CastArg.takeAs<Expr>(); return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor); } + + if (ICS.UserDefined.After.Second == ICK_Pointer_Member && + ToType.getNonReferenceType()->isMemberFunctionPointerType()) + CastKind = CastExpr::CK_BaseToDerivedMemberPointer; From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), CastKind, CastArg.takeAs<Expr>(), @@ -1390,7 +1368,8 @@ QualType Sema::CheckPointerToMemberOperands( LType = Ptr->getPointeeType().getNonReferenceType(); else { Diag(Loc, diag::err_bad_memptr_lhs) - << OpSpelling << 1 << LType << lex->getSourceRange(); + << OpSpelling << 1 << LType + << CodeModificationHint::CreateReplacement(SourceRange(Loc), ".*"); return QualType(); } } @@ -1403,8 +1382,10 @@ QualType Sema::CheckPointerToMemberOperands( // overkill? if (!IsDerivedFrom(LType, Class, Paths) || Paths.isAmbiguous(Context.getCanonicalType(Class))) { + const char *ReplaceStr = isIndirect ? ".*" : "->*"; Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling - << (int)isIndirect << lex->getType() << lex->getSourceRange(); + << (int)isIndirect << lex->getType() << + CodeModificationHint::CreateReplacement(SourceRange(Loc), ReplaceStr); return QualType(); } } @@ -2105,110 +2086,6 @@ Sema::ActOnStartCXXMemberReference(Scope *S, ExprArg Base, SourceLocation OpLoc, return move(Base); } -Sema::OwningExprResult -Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - IdentifierInfo *ClassName, - const CXXScopeSpec &SS, - bool HasTrailingLParen) { - if (SS.isInvalid()) - return ExprError(); - - QualType BaseType; - if (isUnknownSpecialization(SS)) - BaseType = Context.getTypenameType((NestedNameSpecifier *)SS.getScopeRep(), - ClassName); - else { - TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS); - - // FIXME: If Base is dependent, we might not be able to resolve it here. - if (!BaseTy) { - Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type) - << ClassName; - return ExprError(); - } - - BaseType = GetTypeFromParser(BaseTy); - } - - return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind, - SourceRange(ClassNameLoc), - BaseType.getAsOpaquePtr(), - SS, HasTrailingLParen); -} - -Sema::OwningExprResult -Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceRange TypeRange, - TypeTy *T, - const CXXScopeSpec &SS, - bool HasTrailingLParen) { - QualType Type = QualType::getFromOpaquePtr(T); - CanQualType CanType = Context.getCanonicalType(Type); - DeclarationName DtorName = - Context.DeclarationNames.getCXXDestructorName(CanType); - - OwningExprResult Result - = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, - TypeRange.getBegin(), DtorName, DeclPtrTy(), - &SS); - if (Result.isInvalid() || HasTrailingLParen) - return move(Result); - - // The only way a reference to a destructor can be used is to - // immediately call them. Since the next token is not a '(', produce a - // diagnostic and build the call now. - Expr *E = (Expr *)Result.get(); - SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd()); - Diag(E->getLocStart(), diag::err_dtor_expr_without_call) - << isa<CXXPseudoDestructorExpr>(E) - << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); - - return ActOnCallExpr(0, move(Result), ExpectedLParenLoc, - MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc); -} - -Sema::OwningExprResult -Sema::ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - OverloadedOperatorKind OverOpKind, - const CXXScopeSpec *SS) { - if (SS && SS->isInvalid()) - return ExprError(); - - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OverOpKind); - - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, - Name, DeclPtrTy(), SS); -} - -Sema::OwningExprResult -Sema::ActOnConversionOperatorReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - SourceLocation ClassNameLoc, - TypeTy *Ty, - const CXXScopeSpec *SS) { - if (SS && SS->isInvalid()) - return ExprError(); - - //FIXME: Preserve type source info. - QualType ConvType = GetTypeFromParser(Ty); - CanQualType ConvTypeCanon = Context.getCanonicalType(ConvType); - DeclarationName ConvName = - Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon); - - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, - ConvName, DeclPtrTy(), SS); -} - CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, CXXMethodDecl *Method) { MemberExpr *ME = @@ -2333,6 +2210,7 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl))) Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + // FIXME: Do we have to know if there are explicit template arguments? if (Method && !Method->isStatic()) { Ctx = Method->getParent(); if (isa<CXXMethodDecl>(D) && !FunTmpl) @@ -2350,6 +2228,12 @@ bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, // Determine whether the declaration(s) we found are actually in a base // class. If not, this isn't an implicit member reference. ThisType = MD->getThisType(Context); + + // If the type of "this" is dependent, we can't tell if the member is in a + // base class or not, so treat this as a dependent implicit member reference. + if (ThisType->isDependentType()) + return true; + QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx)); QualType ClassType = Context.getTypeDeclType(cast<CXXRecordDecl>(MD->getParent())); diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index dd877c1..93752e1 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -1239,6 +1239,14 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, BaseEnd = Class->bases_end(); Base != BaseEnd; ++Base) { const RecordType *BaseType = Base->getType()->getAs<RecordType>(); + // In dependent contexts, we do ADL twice, and the first time around, + // the base type might be a dependent TemplateSpecializationType, or a + // TemplateTypeParmType. If that happens, simply ignore it. + // FIXME: If we want to support export, we probably need to add the + // namespace of the template in a TemplateSpecializationType, or even + // the classes and namespaces of known non-dependent arguments. + if (!BaseType) + continue; CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); if (AssociatedClasses.insert(BaseDecl)) { // Find the associated namespace for this base class. @@ -1561,7 +1569,7 @@ static void CollectFunctionDecl(Sema::FunctionSet &Functions, Functions.insert(FunTmpl); } -void Sema::ArgumentDependentLookup(DeclarationName Name, +void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, FunctionSet &Functions) { // Find all of the associated namespaces and classes based on the @@ -1572,6 +1580,13 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, AssociatedNamespaces, AssociatedClasses); + QualType T1, T2; + if (Operator) { + T1 = Args[0]->getType(); + if (NumArgs >= 2) + T2 = Args[1]->getType(); + } + // C++ [basic.lookup.argdep]p3: // Let X be the lookup set produced by unqualified lookup (3.4.1) // and let Y be the lookup set produced by argument dependent @@ -1608,7 +1623,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, continue; } - CollectFunctionDecl(Functions, D); + FunctionDecl *Fn; + if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) || + IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context)) + CollectFunctionDecl(Functions, D); } } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ebcf3ad..946e282 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -999,6 +999,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, // here. That is handled by CheckPointerConversion. if (getLangOptions().CPlusPlus && FromPointeeType->isRecordType() && ToPointeeType->isRecordType() && + !RequireCompleteType(From->getLocStart(), FromPointeeType, PDiag()) && IsDerivedFrom(FromPointeeType, ToPointeeType)) { ConvertedType = BuildSimilarlyQualifiedPointerType(FromTypePtr, ToPointeeType, @@ -2444,7 +2445,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, void Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -2489,7 +2490,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -2761,7 +2762,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); if (S) LookupOverloadedOperatorName(Op, S, T1, T2, Functions); - ArgumentDependentLookup(OpName, Args, NumArgs, Functions); + ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions); AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet); AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange); AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet); @@ -3119,9 +3120,8 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S, } } -/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers -/// , if any, found in visible type conversion functions found in ArgExpr's -/// type. +/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers, +/// if any, found in visible type conversion functions found in ArgExpr's type. static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { Qualifiers VRQuals; const RecordType *TyRec; @@ -3139,7 +3139,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); OverloadedFunctionDecl *Conversions = - ClassDecl->getVisibleConversionFunctions(); + ClassDecl->getVisibleConversionFunctions(); for (OverloadedFunctionDecl::function_iterator Func = Conversions->function_begin(); @@ -3887,7 +3887,7 @@ void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, Expr **Args, unsigned NumArgs, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading) { @@ -3908,7 +3908,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, } // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, Args, NumArgs, Functions); + ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions); // Erase all of the candidates we already knew about. // FIXME: This is suboptimal. Is there a better way? @@ -4279,7 +4279,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, } bool HasExplicitTemplateArgs = false; - const TemplateArgument *ExplicitTemplateArgs = 0; + const TemplateArgumentLoc *ExplicitTemplateArgs = 0; unsigned NumExplicitTemplateArgs = 0; // Try to dig out the overloaded function. @@ -4287,10 +4287,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) { Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl()); FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl()); + HasExplicitTemplateArgs = DR->hasExplicitTemplateArgumentList(); + ExplicitTemplateArgs = DR->getTemplateArgs(); + NumExplicitTemplateArgs = DR->getNumTemplateArgs(); } else if (MemberExpr *ME = dyn_cast<MemberExpr>(OvlExpr)) { Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl()); FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl()); - // FIXME: Explicit template arguments + HasExplicitTemplateArgs = ME->hasExplicitTemplateArgumentList(); + ExplicitTemplateArgs = ME->getTemplateArgs(); + NumExplicitTemplateArgs = ME->getNumTemplateArgs(); } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) { TemplateName Name = TIRE->getTemplateName(); Ovl = Name.getAsOverloadedFunctionDecl(); @@ -4367,6 +4372,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // when converting to member pointer. if (Method->isStatic() == IsMember) continue; + + // If we have explicit template arguments, skip non-templates. + if (HasExplicitTemplateArgs) + continue; } else if (IsMember) continue; @@ -4443,7 +4452,7 @@ static void AddOverloadedCallCandidate(Sema &S, AnyFunctionDecl Callee, bool &ArgumentDependentLookup, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, @@ -4475,7 +4484,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, DeclarationName &UnqualifiedName, bool &ArgumentDependentLookup, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, @@ -4543,7 +4552,7 @@ void Sema::AddOverloadedCallCandidates(NamedDecl *Callee, FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, DeclarationName UnqualifiedName, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, @@ -4934,6 +4943,134 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); } +Action::OwningExprResult +Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, + SourceLocation RLoc, + ExprArg Base, ExprArg Idx) { + Expr *Args[2] = { static_cast<Expr*>(Base.get()), + static_cast<Expr*>(Idx.get()) }; + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Subscript); + + // If either side is type-dependent, create an appropriate dependent + // expression. + if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + + OverloadedFunctionDecl *Overloads + = OverloadedFunctionDecl::Create(Context, CurContext, OpName); + + DeclRefExpr *Fn = new (Context) DeclRefExpr(Overloads, Context.OverloadTy, + LLoc, false, false); + + Base.release(); + Idx.release(); + return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, + Args, 2, + Context.DependentTy, + RLoc)); + } + + // Build an empty overload set. + OverloadCandidateSet CandidateSet; + + // Subscript can only be overloaded as a member function. + + // Add operator candidates that are member functions. + AddMemberOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + // Add builtin operator candidates. + AddBuiltinOperatorCandidates(OO_Subscript, LLoc, Args, 2, CandidateSet); + + // Perform overload resolution. + OverloadCandidateSet::iterator Best; + switch (BestViableFunction(CandidateSet, LLoc, Best)) { + case OR_Success: { + // We found a built-in operator or an overloaded operator. + FunctionDecl *FnDecl = Best->Function; + + if (FnDecl) { + // We matched an overloaded operator. Build a call to that + // operator. + + // Convert the arguments. + CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); + if (PerformObjectArgumentInitialization(Args[0], Method) || + PerformCopyInitialization(Args[1], + FnDecl->getParamDecl(0)->getType(), + "passing")) + return ExprError(); + + // Determine the result type + QualType ResultTy + = FnDecl->getType()->getAs<FunctionType>()->getResultType(); + ResultTy = ResultTy.getNonReferenceType(); + + // Build the actual expression node. + Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), + LLoc); + UsualUnaryConversions(FnExpr); + + Base.release(); + Idx.release(); + ExprOwningPtr<CXXOperatorCallExpr> + TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Subscript, + FnExpr, Args, 2, + ResultTy, RLoc)); + + if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall.get(), + FnDecl)) + return ExprError(); + + return MaybeBindToTemporary(TheCall.release()); + } else { + // We matched a built-in operator. Convert the arguments, then + // break out so that we will build the appropriate built-in + // operator node. + if (PerformImplicitConversion(Args[0], Best->BuiltinTypes.ParamTypes[0], + Best->Conversions[0], "passing") || + PerformImplicitConversion(Args[1], Best->BuiltinTypes.ParamTypes[1], + Best->Conversions[1], "passing")) + return ExprError(); + + break; + } + } + + case OR_No_Viable_Function: { + // No viable function; try to create a built-in operation, which will + // produce an error. Then, show the non-viable candidates. + OwningExprResult Result = + CreateBuiltinArraySubscriptExpr(move(Base), LLoc, move(Idx), RLoc); + assert(Result.isInvalid() && + "C++ subscript operator overloading is missing candidates!"); + if (Result.isInvalid()) + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false, + "[]", LLoc); + return move(Result); + } + + case OR_Ambiguous: + Diag(LLoc, diag::err_ovl_ambiguous_oper) + << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true, + "[]", LLoc); + return ExprError(); + + case OR_Deleted: + Diag(LLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() << "[]" + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return ExprError(); + } + + // We matched a built-in operator; build it. + Base.release(); + Idx.release(); + return CreateBuiltinArraySubscriptExpr(Owned(Args[0]), LLoc, + Owned(Args[1]), RLoc); +} + /// BuildCallToMemberFunction - Build a call to a member /// function. MemExpr is the expression that refers to the member /// function (and includes the object parameter), Args/NumArgs are the @@ -4967,10 +5104,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, for (OverloadIterator Func(MemExpr->getMemberDecl()), FuncEnd; Func != FuncEnd; ++Func) { - if ((Method = dyn_cast<CXXMethodDecl>(*Func))) + if ((Method = dyn_cast<CXXMethodDecl>(*Func))) { + // If explicit template arguments were provided, we can't call a + // non-template member function. + if (MemExpr->hasExplicitTemplateArgumentList()) + continue; + AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/false); - else + } else AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func), MemExpr->hasExplicitTemplateArgumentList(), MemExpr->getTemplateArgs(), @@ -5361,8 +5503,14 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); - NewExpr->setType(PE->getSubExpr()->getType()); - return NewExpr; + PE->setSubExpr(NewExpr); + PE->setType(NewExpr->getType()); + } else if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { + Expr *NewExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Fn); + assert(Context.hasSameType(ICE->getSubExpr()->getType(), + NewExpr->getType()) && + "Implicit cast type cannot be determined from overload"); + ICE->setSubExpr(NewExpr); } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) { assert(UnOp->getOpcode() == UnaryOperator::AddrOf && "Can only take the address of an overloaded function"); @@ -5370,18 +5518,19 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { if (Method->isStatic()) { // Do nothing: static member functions aren't any different // from non-member functions. - } else if (QualifiedDeclRefExpr *DRE - = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr())) { - // We have taken the address of a pointer to member - // function. Perform the computation here so that we get the - // appropriate pointer to member type. - DRE->setDecl(Fn); - DRE->setType(Fn->getType()); - QualType ClassType - = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); - E->setType(Context.getMemberPointerType(Fn->getType(), - ClassType.getTypePtr())); - return E; + } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr())) { + if (DRE->getQualifier()) { + // We have taken the address of a pointer to member + // function. Perform the computation here so that we get the + // appropriate pointer to member type. + DRE->setDecl(Fn); + DRE->setType(Fn->getType()); + QualType ClassType + = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext())); + E->setType(Context.getMemberPointerType(Fn->getType(), + ClassType.getTypePtr())); + return E; + } } // FIXME: TemplateIdRefExpr referring to a member function template // specialization! @@ -5393,26 +5542,35 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { return UnOp; } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) { assert((isa<OverloadedFunctionDecl>(DR->getDecl()) || - isa<FunctionTemplateDecl>(DR->getDecl())) && - "Expected overloaded function or function template"); + isa<FunctionTemplateDecl>(DR->getDecl()) || + isa<FunctionDecl>(DR->getDecl())) && + "Expected function or function template"); DR->setDecl(Fn); E->setType(Fn->getType()); } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) { MemExpr->setMemberDecl(Fn); E->setType(Fn->getType()); } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) { - // FIXME: We should capture the template arguments here. - if (NestedNameSpecifier *Qualifier = TID->getQualifier()) - E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(), - TID->getTemplateNameLoc(), - /*FIXME?*/false, /*FIXME?*/false, - TID->getQualifierRange(), - Qualifier); - else - E = new (Context) DeclRefExpr(Fn, Fn->getType(), - TID->getTemplateNameLoc()); + E = DeclRefExpr::Create(Context, + TID->getQualifier(), TID->getQualifierRange(), + Fn, TID->getTemplateNameLoc(), + true, + TID->getLAngleLoc(), + TID->getTemplateArgs(), + TID->getNumTemplateArgs(), + TID->getRAngleLoc(), + Fn->getType(), + /*FIXME?*/false, /*FIXME?*/false); - TID->Destroy(Context); + // FIXME: Don't destroy TID here, since we need its template arguments + // to survive. + // TID->Destroy(Context); + } else if (isa<UnresolvedFunctionNameExpr>(E)) { + return DeclRefExpr::Create(Context, + /*Qualifier=*/0, + /*QualifierRange=*/SourceRange(), + Fn, E->getLocStart(), + Fn->getType(), false, false); } else { assert(false && "Invalid reference to overloaded function"); } diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 1453424..6a65bd1 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -70,7 +70,7 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { SourceLocation Loc; SourceRange R1, R2; - if (!E->isUnusedResultAWarning(Loc, R1, R2)) + if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) return; // Okay, we have an unused result. Depending on what the base expression is, diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 0f22320..3c56358 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -98,29 +98,43 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { } TemplateNameKind Sema::isTemplateName(Scope *S, - const IdentifierInfo &II, - SourceLocation IdLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult) { + DeclarationName TName; + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + TName = DeclarationName(Name.Identifier); + break; + + case UnqualifiedId::IK_OperatorFunctionId: + TName = Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); + break; + + default: + return TNK_Non_template; + } + // Determine where to perform name lookup DeclContext *LookupCtx = 0; bool isDependent = false; if (ObjectTypePtr) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. - assert((!SS || !SS->isSet()) && - "ObjectType and scope specifier cannot coexist"); + assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); - } else if (SS && SS->isSet()) { + } else if (SS.isSet()) { // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. - LookupCtx = computeDeclContext(*SS, EnteringContext); - isDependent = isDependentScopeSpecifier(*SS); + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); } LookupResult Found; @@ -132,10 +146,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // nested-name-specifier. // The declaration context must be complete. - if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS)) + if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(SS)) return TNK_Non_template; - LookupQualifiedName(Found, LookupCtx, &II, LookupOrdinaryName); + LookupQualifiedName(Found, LookupCtx, TName, LookupOrdinaryName); if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) { // C++ [basic.lookup.classref]p1: @@ -150,7 +164,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // // FIXME: When we're instantiating a template, do we actually have to // look in the scope of the template? Seems fishy... - LookupName(Found, S, &II, LookupOrdinaryName); + LookupName(Found, S, TName, LookupOrdinaryName); ObjectTypeSearchedInScope = true; } } else if (isDependent) { @@ -158,7 +172,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, return TNK_Non_template; } else { // Perform unqualified name lookup in the current scope. - LookupName(Found, S, &II, LookupOrdinaryName); + LookupName(Found, S, TName, LookupOrdinaryName); } // FIXME: Cope with ambiguous name-lookup results. @@ -177,7 +191,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // postfix-expression and [...] // LookupResult FoundOuter; - LookupName(FoundOuter, S, &II, LookupOrdinaryName); + LookupName(FoundOuter, S, TName, LookupOrdinaryName); // FIXME: Handle ambiguities in this lookup better NamedDecl *OuterTemplate = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); @@ -194,8 +208,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // entity as the one found in the class of the object expression, // otherwise the program is ill-formed. if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) { - Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous) - << &II; + Diag(Name.getSourceRange().getBegin(), + diag::err_nested_name_member_ref_lookup_ambiguous) + << TName + << Name.getSourceRange(); Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type) << QualType::getFromOpaquePtr(ObjectTypePtr); Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope); @@ -206,9 +222,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, } } - if (SS && SS->isSet() && !SS->isInvalid()) { + if (SS.isSet() && !SS.isInvalid()) { NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(Template)) TemplateResult @@ -321,8 +337,11 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, TypeTy *DefaultT) { TemplateTypeParmDecl *Parm = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>()); - // FIXME: Preserve type source info. - QualType Default = GetTypeFromParser(DefaultT); + + DeclaratorInfo *DefaultDInfo; + GetTypeFromParser(DefaultT, &DefaultDInfo); + + assert(DefaultDInfo && "expected source information for type"); // C++0x [temp.param]p9: // A default template-argument may be specified for any kind of @@ -337,12 +356,12 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, // FIXME: Implement this check! Needs a recursive walk over the types. // Check the template argument itself. - if (CheckTemplateArgument(Parm, Default, DefaultLoc)) { + if (CheckTemplateArgument(Parm, DefaultDInfo)) { Parm->setInvalidDecl(); return; } - Parm->setDefaultArgument(Default, DefaultLoc, false); + Parm->setDefaultArgument(DefaultDInfo, false); } /// \brief Check that the type of a non-type template parameter is @@ -610,11 +629,19 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SemanticContext = PrevDecl->getDeclContext(); } else { // Declarations in outer scopes don't matter. However, the outermost - // context we computed is the semntic context for our new + // context we computed is the semantic context for our new // declaration. PrevDecl = 0; SemanticContext = OutermostContext; } + + if (CurContext->isDependentContext()) { + // If this is a dependent context, we don't want to link the friend + // class template to the template in scope, because that would perform + // checking of the template parameter lists that can't be performed + // until the outer context is instantiated. + PrevDecl = 0; + } } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) PrevDecl = 0; @@ -843,7 +870,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SawParameterPack = true; ParameterPackLoc = NewTypeParm->getLocation(); } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && - NewTypeParm->hasDefaultArgument()) { + NewTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); SawDefaultArgument = true; @@ -853,8 +880,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge the default argument from the old declaration to the // new declaration. SawDefaultArgument = true; - NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgument(), - OldTypeParm->getDefaultArgumentLoc(), + NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(), true); PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc(); } else if (NewTypeParm->hasDefaultArgument()) { @@ -1096,24 +1122,28 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, /// into template arguments used by semantic analysis. void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, SourceLocation *TemplateArgLocs, - llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) { + llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) { TemplateArgs.reserve(TemplateArgsIn.size()); void **Args = TemplateArgsIn.getArgs(); bool *ArgIsType = TemplateArgsIn.getArgIsType(); for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) { - TemplateArgs.push_back( - ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg], - //FIXME: Preserve type source info. - Sema::GetTypeFromParser(Args[Arg])) - : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg]))); + if (ArgIsType[Arg]) { + DeclaratorInfo *DI; + QualType T = Sema::GetTypeFromParser(Args[Arg], &DI); + if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]); + TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI)); + } else { + Expr *E = reinterpret_cast<Expr *>(Args[Arg]); + TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E)); + } } } QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { TemplateDecl *Template = Name.getAsTemplateDecl(); @@ -1155,7 +1185,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, Converted.flatSize()); // FIXME: CanonType is not actually the canonical type, and unfortunately - // it is a TemplateTypeSpecializationType that we will never use again. + // it is a TemplateSpecializationType that we will never use again. // In the future, we need to teach getTemplateSpecializationType to only // build the canonical type and return that to us. CanonType = Context.getCanonicalType(CanonType); @@ -1190,7 +1220,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - //FIXME: Preserve type source info. return Context.getTemplateSpecializationType(Name, TemplateArgs, NumTemplateArgs, CanonType); } @@ -1199,13 +1228,13 @@ Action::TypeResult Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, + SourceLocation *TemplateArgLocsIn, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs); QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, TemplateArgs.data(), @@ -1216,7 +1245,16 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, if (Result.isNull()) return true; - return Result.getAsOpaquePtr(); + DeclaratorInfo *DI = Context.CreateDeclaratorInfo(Result); + TemplateSpecializationTypeLoc TL + = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); + TL.setTemplateNameLoc(TemplateLoc); + TL.setLAngleLoc(LAngleLoc); + TL.setRAngleLoc(RAngleLoc); + for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) + TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo()); + + return CreateLocInfoType(Result, DI).getAsOpaquePtr(); } Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, @@ -1226,7 +1264,9 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, if (TypeResult.isInvalid()) return Sema::TypeResult(); - QualType Type = QualType::getFromOpaquePtr(TypeResult.get()); + // FIXME: preserve source info, ideally without copying the DI. + DeclaratorInfo *DI; + QualType Type = GetTypeFromParser(TypeResult.get(), &DI); // Verify the tag specifier. TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); @@ -1256,7 +1296,7 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { // FIXME: Can we do any checking at this point? I guess we could check the @@ -1296,13 +1336,13 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, + SourceLocation *TemplateArgSLs, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs); TemplateArgsIn.release(); return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), @@ -1312,41 +1352,6 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, RAngleLoc); } -Sema::OwningExprResult -Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base, - SourceLocation OpLoc, - tok::TokenKind OpKind, - const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc) { - TemplateName Template = TemplateD.getAsVal<TemplateName>(); - - // FIXME: We're going to end up looking up the template based on its name, - // twice! - DeclarationName Name; - if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) - Name = ActualTemplate->getDeclName(); - else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl()) - Name = Ovl->getDeclName(); - else - Name = Template.getAsDependentTemplateName()->getName(); - - // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); - TemplateArgsIn.release(); - - // Do we have the save the actual template name? We might need it... - return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc, - Name, true, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, DeclPtrTy(), &SS); -} - /// \brief Form a dependent template name. /// /// This action forms a dependent template name given the template @@ -1356,9 +1361,8 @@ Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base, /// of the "template" keyword, and "apply" is the \p Name. Sema::TemplateTy Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - const IdentifierInfo &Name, - SourceLocation NameLoc, const CXXScopeSpec &SS, + UnqualifiedId &Name, TypeTy *ObjectType) { if ((ObjectType && computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) || @@ -1380,11 +1384,13 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // "template" keyword is now permitted). We follow the C++0x // rules, even in C++03 mode, retroactively applying the DR. TemplateTy Template; - TemplateNameKind TNK = isTemplateName(0, Name, NameLoc, &SS, ObjectType, + TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, false, Template); if (TNK == TNK_Non_template) { - Diag(NameLoc, diag::err_template_kw_refers_to_non_template) - << &Name; + Diag(Name.getSourceRange().getBegin(), + diag::err_template_kw_refers_to_non_template) + << GetNameFromUnqualifiedId(Name) + << Name.getSourceRange(); return TemplateTy(); } @@ -1393,12 +1399,32 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, NestedNameSpecifier *Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name)); + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + return TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.Identifier)); + + case UnqualifiedId::IK_OperatorFunctionId: + return TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.OperatorFunctionId.Operator)); + + default: + break; + } + + Diag(Name.getSourceRange().getBegin(), + diag::err_template_kw_refers_to_non_template) + << GetNameFromUnqualifiedId(Name) + << Name.getSourceRange(); + return TemplateTy(); } bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, - const TemplateArgument &Arg, + const TemplateArgumentLoc &AL, TemplateArgumentListBuilder &Converted) { + const TemplateArgument &Arg = AL.getArgument(); + // Check template type parameter. if (Arg.getKind() != TemplateArgument::Type) { // C++ [temp.arg.type]p1: @@ -1407,19 +1433,19 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, // We have a template type parameter but the template argument // is not a type. - Diag(Arg.getLocation(), diag::err_template_arg_must_be_type); + SourceRange SR = AL.getSourceRange(); + Diag(SR.getBegin(), diag::err_template_arg_must_be_type) << SR; Diag(Param->getLocation(), diag::note_template_param_here); return true; } - if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation())) + if (CheckTemplateArgument(Param, AL.getSourceDeclaratorInfo())) return true; // Add the converted template type argument. Converted.Append( - TemplateArgument(Arg.getLocation(), - Context.getCanonicalType(Arg.getAsType()))); + TemplateArgument(Context.getCanonicalType(Arg.getAsType()))); return false; } @@ -1428,7 +1454,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, bool PartialTemplateArgs, @@ -1474,7 +1500,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; // Decode the template argument - TemplateArgument Arg; + TemplateArgumentLoc Arg; + if (ArgIdx >= NumArgs) { // Retrieve the default template argument from the template // parameter. @@ -1489,11 +1516,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (!TTP->hasDefaultArgument()) break; - QualType ArgType = TTP->getDefaultArgument(); + DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo(); // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. - if (ArgType->isDependentType()) { + if (ArgType->getType()->isDependentType()) { InstantiatingTemplate Inst(*this, TemplateLoc, Template, Converted.getFlatArguments(), Converted.flatSize(), @@ -1507,10 +1534,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TTP->getDeclName()); } - if (ArgType.isNull()) + if (!ArgType) return true; - Arg = TemplateArgument(TTP->getLocation(), ArgType); + Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (!NTTP->hasDefaultArgument()) @@ -1530,7 +1557,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (E.isInvalid()) return true; - Arg = TemplateArgument(E.takeAs<Expr>()); + Expr *Ex = E.takeAs<Expr>(); + Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex); } else { TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); @@ -1539,7 +1567,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; // FIXME: Subst default argument - Arg = TemplateArgument(TempParm->getDefaultArgument()); + Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()), + TempParm->getDefaultArgument()); } } else { // Retrieve the template argument produced by the user. @@ -1592,13 +1621,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, } } - switch (Arg.getKind()) { + switch (Arg.getArgument().getKind()) { case TemplateArgument::Null: assert(false && "Should never see a NULL template argument here"); break; case TemplateArgument::Expression: { - Expr *E = Arg.getAsExpr(); + Expr *E = Arg.getArgument().getAsExpr(); TemplateArgument Result; if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) Invalid = true; @@ -1611,10 +1640,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Integral: // We've already checked this template argument, so just copy // it to the list of converted arguments. - Converted.Append(Arg); + Converted.Append(Arg.getArgument()); break; - case TemplateArgument::Type: + case TemplateArgument::Type: { // We have a non-type template parameter but the template // argument is a type. @@ -1625,14 +1654,17 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // // We warn specifically about this case, since it can be rather // confusing for users. - if (Arg.getAsType()->isFunctionType()) - Diag(Arg.getLocation(), diag::err_template_arg_nontype_ambig) - << Arg.getAsType(); + QualType T = Arg.getArgument().getAsType(); + SourceRange SR = Arg.getSourceRange(); + if (T->isFunctionType()) + Diag(SR.getBegin(), diag::err_template_arg_nontype_ambig) + << SR << T; else - Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr); + Diag(SR.getBegin(), diag::err_template_arg_must_be_expr) << SR; Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; break; + } case TemplateArgument::Pack: assert(0 && "FIXME: Implement!"); @@ -1643,13 +1675,13 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - switch (Arg.getKind()) { + switch (Arg.getArgument().getKind()) { case TemplateArgument::Null: assert(false && "Should never see a NULL template argument here"); break; case TemplateArgument::Expression: { - Expr *ArgExpr = Arg.getAsExpr(); + Expr *ArgExpr = Arg.getArgument().getAsExpr(); if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) @@ -1658,7 +1690,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Add the converted template argument. Decl *D = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl(); - Converted.Append(TemplateArgument(Arg.getLocation(), D)); + Converted.Append(TemplateArgument(D)); continue; } } @@ -1675,7 +1707,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Declaration: // We've already checked this template argument, so just copy // it to the list of converted arguments. - Converted.Append(Arg); + Converted.Append(Arg.getArgument()); break; case TemplateArgument::Integral: @@ -1698,7 +1730,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, /// This routine implements the semantics of C++ [temp.arg.type]. It /// returns true if an error occurred, and false otherwise. bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, - QualType Arg, SourceLocation ArgLoc) { + DeclaratorInfo *ArgInfo) { + assert(ArgInfo && "invalid DeclaratorInfo"); + QualType Arg = ArgInfo->getType(); + // C++ [temp.arg.type]p2: // A local type, a type with no linkage, an unnamed type or a type // compounded from any of these types shall not be used as a @@ -1710,12 +1745,14 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, Tag = EnumT; else if (const RecordType *RecordT = Arg->getAs<RecordType>()) Tag = RecordT; - if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) - return Diag(ArgLoc, diag::err_template_arg_local_type) - << QualType(Tag, 0); - else if (Tag && !Tag->getDecl()->getDeclName() && + if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) { + SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange(); + return Diag(SR.getBegin(), diag::err_template_arg_local_type) + << QualType(Tag, 0) << SR; + } else if (Tag && !Tag->getDecl()->getDeclName() && !Tag->getDecl()->getTypedefForAnonDecl()) { - Diag(ArgLoc, diag::err_template_arg_unnamed_type); + SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange(); + Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR; Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here); return true; } @@ -1845,7 +1882,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { // template-parameter shall be one of: [...] // // -- a pointer to member expressed as described in 5.3.1. - QualifiedDeclRefExpr *DRE = 0; + DeclRefExpr *DRE = 0; // Ignore (and complain about) any excess parentheses. while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { @@ -1860,8 +1897,11 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { } if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(Arg)) - if (UnOp->getOpcode() == UnaryOperator::AddrOf) - DRE = dyn_cast<QualifiedDeclRefExpr>(UnOp->getSubExpr()); + if (UnOp->getOpcode() == UnaryOperator::AddrOf) { + DRE = dyn_cast<DeclRefExpr>(UnOp->getSubExpr()); + if (DRE && !DRE->getQualifier()) + DRE = 0; + } if (!DRE) return Diag(Arg->getSourceRange().getBegin(), @@ -2012,7 +2052,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return false; } - Converted = TemplateArgument(StartLoc, Value, + Converted = TemplateArgument(Value, ParamType->isEnumeralType() ? ParamType : IntegerType); return false; @@ -2086,7 +2126,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Member) Member = cast<NamedDecl>(Member->getCanonicalDecl()); - Converted = TemplateArgument(StartLoc, Member); + Converted = TemplateArgument(Member); return false; } @@ -2096,7 +2136,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Entity) Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(StartLoc, Entity); + Converted = TemplateArgument(Entity); return false; } @@ -2136,7 +2176,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Entity) Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(StartLoc, Entity); + Converted = TemplateArgument(Entity); return false; } @@ -2177,7 +2217,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(StartLoc, Entity); + Converted = TemplateArgument(Entity); return false; } @@ -2207,7 +2247,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (Member) Member = cast<NamedDecl>(Member->getCanonicalDecl()); - Converted = TemplateArgument(StartLoc, Member); + Converted = TemplateArgument(Member); return false; } @@ -2719,7 +2759,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, if (TTP->hasDefaultArgument()) { Diag(TTP->getDefaultArgumentLoc(), diag::err_default_arg_in_partial_spec); - TTP->setDefaultArgument(QualType(), SourceLocation(), false); + TTP->removeDefaultArgument(); } } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { @@ -2778,7 +2818,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); // Check that the template argument list is well-formed for this @@ -2877,8 +2917,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Converted.flatSize()); // Create a new class template partial specialization declaration node. - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); ClassTemplatePartialSpecializationDecl *Partial @@ -2888,6 +2926,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateParams, ClassTemplate, Converted, + TemplateArgs.data(), + TemplateArgs.size(), PrevPartial); if (PrevPartial) { @@ -2898,6 +2938,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } Specialization = Partial; + // If we are providing an explicit specialization of a member class + // template specialization, make a note of that. + if (PrevPartial && PrevPartial->getInstantiatedFromMember()) + PrevPartial->setMemberSpecialization(); + // Check that all of the template parameters of the class template // partial specialization are deducible from the template // arguments. If not, this class template partial specialization @@ -2905,6 +2950,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, llvm::SmallVector<bool, 8> DeducibleParams; DeducibleParams.resize(TemplateParams->size()); MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, + TemplateParams->getDepth(), DeducibleParams); unsigned NumNonDeducible = 0; for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) @@ -3070,8 +3116,6 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, /// for those cases where they are required and determining whether the /// new specialization/instantiation will have any effect. /// -/// \param S the semantic analysis object. -/// /// \param NewLoc the location of the new explicit specialization or /// instantiation. /// @@ -3089,14 +3133,13 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, /// /// \returns true if there was an error that should prevent the introduction of /// the new declaration into the AST, false otherwise. -static bool -CheckSpecializationInstantiationRedecl(Sema &S, - SourceLocation NewLoc, - TemplateSpecializationKind NewTSK, - NamedDecl *PrevDecl, - TemplateSpecializationKind PrevTSK, - SourceLocation PrevPointOfInstantiation, - bool &SuppressNew) { +bool +Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, + TemplateSpecializationKind NewTSK, + NamedDecl *PrevDecl, + TemplateSpecializationKind PrevTSK, + SourceLocation PrevPointOfInstantiation, + bool &SuppressNew) { SuppressNew = false; switch (NewTSK) { @@ -3134,9 +3177,9 @@ CheckSpecializationInstantiationRedecl(Sema &S, // before the first use of that specialization that would cause an // implicit instantiation to take place, in every translation unit in // which such a use occurs; no diagnostic is required. - S.Diag(NewLoc, diag::err_specialization_after_instantiation) + Diag(NewLoc, diag::err_specialization_after_instantiation) << PrevDecl; - S.Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here) + Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here) << (PrevTSK != TSK_ImplicitInstantiation); return true; @@ -3169,10 +3212,10 @@ CheckSpecializationInstantiationRedecl(Sema &S, // If an entity is the subject of both an explicit instantiation // declaration and an explicit instantiation definition in the same // translation unit, the definition shall follow the declaration. - S.Diag(NewLoc, - diag::err_explicit_instantiation_declaration_after_definition); - S.Diag(PrevPointOfInstantiation, - diag::note_explicit_instantiation_definition_here); + Diag(NewLoc, + diag::err_explicit_instantiation_declaration_after_definition); + Diag(PrevPointOfInstantiation, + diag::note_explicit_instantiation_definition_here); assert(PrevPointOfInstantiation.isValid() && "Explicit instantiation without point of instantiation?"); SuppressNew = true; @@ -3198,10 +3241,10 @@ CheckSpecializationInstantiationRedecl(Sema &S, // In C++98/03 mode, we only give an extension warning here, because it // is not not harmful to try to explicitly instantiate something that // has been explicitly specialized. - if (!S.getLangOptions().CPlusPlus0x) { - S.Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization) + if (!getLangOptions().CPlusPlus0x) { + Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization) << PrevDecl; - S.Diag(PrevDecl->getLocation(), + Diag(PrevDecl->getLocation(), diag::note_previous_template_specialization); } SuppressNew = true; @@ -3217,10 +3260,10 @@ CheckSpecializationInstantiationRedecl(Sema &S, // For a given template and a given set of template-arguments, // - an explicit instantiation definition shall appear at most once // in a program, - S.Diag(NewLoc, diag::err_explicit_instantiation_duplicate) + Diag(NewLoc, diag::err_explicit_instantiation_duplicate) << PrevDecl; - S.Diag(PrevPointOfInstantiation, - diag::note_previous_explicit_instantiation); + Diag(PrevPointOfInstantiation, + diag::note_previous_explicit_instantiation); SuppressNew = true; return false; } @@ -3264,7 +3307,7 @@ bool Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, bool HasExplicitTemplateArgs, SourceLocation LAngleLoc, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, SourceLocation RAngleLoc, NamedDecl *&PrevDecl) { @@ -3333,7 +3376,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // C++ [temp.expl.spec]p6: // If a template, a member template or the member of a class template is - // explicitly specialized then that spe- cialization shall be declared + // explicitly specialized then that specialization shall be declared // before the first use of that specialization that would cause an implicit // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. @@ -3620,7 +3663,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, : TSK_ExplicitInstantiationDeclaration; // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); // Check that the template argument list is well-formed for this @@ -3659,7 +3702,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, if (PrevDecl) { bool SuppressNew = false; - if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK, + if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, PrevDecl, PrevDecl->getSpecializationKind(), PrevDecl->getPointOfInstantiation(), @@ -3723,8 +3766,6 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setLexicalDeclContext(CurContext); CurContext->addDecl(Specialization); - Specialization->setPointOfInstantiation(TemplateNameLoc); - // C++ [temp.explicit]p3: // A definition of a class template or class member template // shall be in scope at the point of the explicit instantiation of @@ -3736,8 +3777,12 @@ Sema::ActOnExplicitInstantiation(Scope *S, = cast_or_null<ClassTemplateSpecializationDecl>( Specialization->getDefinition(Context)); if (!Def) - InstantiateClassTemplateSpecialization(Specialization, TSK); - else // Instantiate the members of this class template specialization. + InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); + + // Instantiate the members of this class template specialization. + Def = cast_or_null<ClassTemplateSpecializationDecl>( + Specialization->getDefinition(Context)); + if (Def) InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); return DeclPtrTy::make(Specialization); @@ -3819,7 +3864,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); bool SuppressNew = false; assert(MSInfo && "No member specialization information?"); - if (CheckSpecializationInstantiationRedecl(*this, TemplateLoc, TSK, + if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK, PrevDecl, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), @@ -3843,13 +3888,21 @@ Sema::ActOnExplicitInstantiation(Scope *S, Diag(Pattern->getLocation(), diag::note_forward_declaration) << Pattern; return true; - } else if (InstantiateClass(NameLoc, Record, Def, - getTemplateInstantiationArgs(Record), - TSK)) - return true; - } else // Instantiate all of the members of the class. - InstantiateClassMembers(NameLoc, RecordDef, - getTemplateInstantiationArgs(Record), TSK); + } else { + if (InstantiateClass(NameLoc, Record, Def, + getTemplateInstantiationArgs(Record), + TSK)) + return true; + + RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); + if (!RecordDef) + return true; + } + } + + // Instantiate all of the members of the class. + InstantiateClassMembers(NameLoc, RecordDef, + getTemplateInstantiationArgs(Record), TSK); // FIXME: We don't have any representation for explicit instantiations of // member classes. Such a representation is not needed for compilation, but it @@ -3968,8 +4021,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); assert(MSInfo && "Missing static data member specialization info?"); bool SuppressNew = false; - if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK, - Prev, + if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), SuppressNew)) @@ -3990,9 +4042,9 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; - llvm::SmallVector<TemplateArgument, 16> TemplateArgs; - if (D.getKind() == Declarator::DK_TemplateId) { - TemplateIdAnnotation *TemplateId = D.getTemplateId(); + llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getName().TemplateId; ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->getTemplateArgIsType(), @@ -4068,7 +4120,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (PrevDecl) { bool SuppressNew = false; - if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK, + if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, PrevDecl, PrevDecl->getTemplateSpecializationKind(), PrevDecl->getPointOfInstantiation(), @@ -4095,7 +4147,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // // C++98 has the same restriction, just worded differently. FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate(); - if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl && + if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl && D.getCXXScopeSpec().isSet() && !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) Diag(D.getIdentifierLoc(), @@ -4277,6 +4329,13 @@ namespace { /// \brief Returns the name of the entity whose type is being rebuilt. DeclarationName getBaseEntity() { return Entity; } + /// \brief Sets the "base" location and entity when that + /// information is known based on another transformation. + void setBase(SourceLocation Loc, DeclarationName Entity) { + this->Loc = Loc; + this->Entity = Entity; + } + /// \brief Transforms an expression by returning the expression itself /// (an identity function). /// @@ -4290,25 +4349,13 @@ namespace { /// refers to a member of the current instantiation, and then /// type-checking and building a QualifiedNameType (when possible). QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL); - QualType TransformTypenameType(TypenameType *T); }; } QualType CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL) { - QualType Result = TransformTypenameType(TL.getTypePtr()); - if (Result.isNull()) - return QualType(); - - TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); - - return Result; -} - -QualType -CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) { + TypenameType *T = TL.getTypePtr(); NestedNameSpecifier *NNS = TransformNestedNameSpecifier(T->getQualifier(), @@ -4322,12 +4369,14 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) { CXXScopeSpec SS; SS.setRange(SourceRange(getBaseLocation())); SS.setScopeRep(NNS); + + QualType Result; if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0) - return QualType(T, 0); + Result = QualType(T, 0); // Rebuild the typename type, which will probably turn into a // QualifiedNameType. - if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { + else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { QualType NewTemplateId = TransformType(QualType(TemplateId, 0)); if (NewTemplateId.isNull()) @@ -4335,12 +4384,16 @@ CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) { if (NNS == T->getQualifier() && NewTemplateId == QualType(TemplateId, 0)) - return QualType(T, 0); - - return getDerived().RebuildTypenameType(NNS, NewTemplateId); - } + Result = QualType(T, 0); + else + Result = getDerived().RebuildTypenameType(NNS, NewTemplateId); + } else + Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), + SourceRange(TL.getNameLoc())); - return getDerived().RebuildTypenameType(NNS, T->getIdentifier()); + TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; } /// \brief Rebuilds a type within the context of the current instantiation. diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 2a44f83..7b5ad7f 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -90,7 +90,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, Value.extOrTrunc(AllowedBits); Value.setIsSigned(T->isSignedIntegerType()); - Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T); + Deduced[NTTP->getIndex()] = TemplateArgument(Value, T); return Sema::TDK_Success; } @@ -102,7 +102,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, if (PrevValuePtr->isNegative()) { Info.Param = NTTP; Info.FirstArg = Deduced[NTTP->getIndex()]; - Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType()); + Info.SecondArg = TemplateArgument(Value, NTTP->getType()); return Sema::TDK_Inconsistent; } @@ -115,7 +115,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, if (Value != PrevValue) { Info.Param = NTTP; Info.FirstArg = Deduced[NTTP->getIndex()]; - Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType()); + Info.SecondArg = TemplateArgument(Value, NTTP->getType()); return Sema::TDK_Inconsistent; } @@ -433,7 +433,7 @@ DeduceTemplateArguments(ASTContext &Context, if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) { Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index)); Info.FirstArg = Deduced[Index]; - Info.SecondArg = TemplateArgument(SourceLocation(), Arg); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_InconsistentQuals; } @@ -445,7 +445,7 @@ DeduceTemplateArguments(ASTContext &Context, DeducedType = Context.getCanonicalType(DeducedType); if (Deduced[Index].isNull()) - Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType); + Deduced[Index] = TemplateArgument(DeducedType); else { // C++ [temp.deduct.type]p2: // [...] If type deduction cannot be done for any P/A pair, or if for @@ -457,7 +457,7 @@ DeduceTemplateArguments(ASTContext &Context, Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index)); Info.FirstArg = Deduced[Index]; - Info.SecondArg = TemplateArgument(SourceLocation(), Arg); + Info.SecondArg = TemplateArgument(Arg); return Sema::TDK_Inconsistent; } } @@ -465,8 +465,8 @@ DeduceTemplateArguments(ASTContext &Context, } // Set up the template argument deduction information for a failure. - Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn); - Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn); + Info.FirstArg = TemplateArgument(ParamIn); + Info.SecondArg = TemplateArgument(ArgIn); // Check the cv-qualifiers on the parameter and argument types. if (!(TDF & TDF_IgnoreQualifiers)) { @@ -695,7 +695,7 @@ DeduceTemplateArguments(ASTContext &Context, CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl()); for (CXXRecordDecl::base_class_iterator Base = Next->bases_begin(), BaseEnd = Next->bases_end(); - Base != BaseEnd; ++Base) { + Base != BaseEnd; ++Base) { assert(Base->getType()->isRecordType() && "Base class that isn't a record?"); ToVisit.push_back(Base->getType()->getAs<RecordType>()); @@ -982,18 +982,41 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // and are equivalent to the template arguments originally provided // to the class template. ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate(); - const TemplateArgumentList &PartialTemplateArgs = Partial->getTemplateArgs(); - for (unsigned I = 0, N = PartialTemplateArgs.flat_size(); I != N; ++I) { + const TemplateArgumentLoc *PartialTemplateArgs + = Partial->getTemplateArgsAsWritten(); + unsigned N = Partial->getNumTemplateArgsAsWritten(); + llvm::SmallVector<TemplateArgumentLoc, 16> InstArgs(N); + for (unsigned I = 0; I != N; ++I) { Decl *Param = const_cast<NamedDecl *>( ClassTemplate->getTemplateParameters()->getParam(I)); - TemplateArgument InstArg - = Subst(PartialTemplateArgs[I], - MultiLevelTemplateArgumentList(*DeducedArgumentList)); - if (InstArg.isNull()) { + if (Subst(PartialTemplateArgs[I], InstArgs[I], + MultiLevelTemplateArgumentList(*DeducedArgumentList))) { Info.Param = makeTemplateParameter(Param); - Info.FirstArg = PartialTemplateArgs[I]; + Info.FirstArg = PartialTemplateArgs[I].getArgument(); return TDK_SubstitutionFailure; } + } + + TemplateArgumentListBuilder ConvertedInstArgs( + ClassTemplate->getTemplateParameters(), N); + + if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(), + /*LAngle*/ SourceLocation(), + InstArgs.data(), N, + /*RAngle*/ SourceLocation(), + false, ConvertedInstArgs)) { + // FIXME: fail with more useful information? + return TDK_SubstitutionFailure; + } + + for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) { + // We don't really care if we overwrite the internal structures of + // the arg list builder, because we're going to throw it all away. + TemplateArgument &InstArg + = const_cast<TemplateArgument&>(ConvertedInstArgs.getFlatArguments()[I]); + + Decl *Param = const_cast<NamedDecl *>( + ClassTemplate->getTemplateParameters()->getParam(I)); if (InstArg.getKind() == TemplateArgument::Expression) { // When the argument is an expression, check the expression result @@ -1004,7 +1027,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, = dyn_cast<NonTypeTemplateParmDecl>(Param)) { if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) { Info.Param = makeTemplateParameter(Param); - Info.FirstArg = PartialTemplateArgs[I]; + Info.FirstArg = Partial->getTemplateArgs()[I]; return TDK_SubstitutionFailure; } } else if (TemplateTemplateParmDecl *TTP @@ -1013,7 +1036,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr); if (!DRE || CheckTemplateArgument(TTP, DRE)) { Info.Param = makeTemplateParameter(Param); - Info.FirstArg = PartialTemplateArgs[I]; + Info.FirstArg = Partial->getTemplateArgs()[I]; return TDK_SubstitutionFailure; } } @@ -1072,7 +1095,7 @@ static bool isSimpleTemplateIdType(QualType T) { Sema::TemplateDeductionResult Sema::SubstituteExplicitTemplateArguments( FunctionTemplateDecl *FunctionTemplate, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, @@ -1290,7 +1313,7 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, @@ -1460,7 +1483,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, bool HasExplicitTemplateArgs, - const TemplateArgument *ExplicitTemplateArgs, + const TemplateArgumentLoc *ExplicitTemplateArgs, unsigned NumExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, @@ -1643,15 +1666,15 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, // performed on the types used for partial ordering: // - If P is a reference type, P is replaced by the type referred to. CanQual<ReferenceType> ParamRef = Param->getAs<ReferenceType>(); - if (ParamRef) + if (!ParamRef.isNull()) Param = ParamRef->getPointeeType(); // - If A is a reference type, A is replaced by the type referred to. CanQual<ReferenceType> ArgRef = Arg->getAs<ReferenceType>(); - if (ArgRef) + if (!ArgRef.isNull()) Arg = ArgRef->getPointeeType(); - if (QualifierComparisons && ParamRef && ArgRef) { + if (QualifierComparisons && !ParamRef.isNull() && !ArgRef.isNull()) { // C++0x [temp.deduct.partial]p6: // If both P and A were reference types (before being replaced with the // type referred to above), determine which of the two types (if any) is @@ -1690,6 +1713,7 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, static void MarkUsedTemplateParameters(Sema &SemaRef, QualType T, bool OnlyDeduced, + unsigned Level, llvm::SmallVectorImpl<bool> &Deduced); /// \brief Determine whether the function template \p FT1 is at least as @@ -1782,18 +1806,22 @@ static bool isAtLeastAsSpecializedAs(Sema &S, case TPOC_Call: { unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs()); for (unsigned I = 0; I != NumParams; ++I) - ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, + ::MarkUsedTemplateParameters(S, Proto2->getArgType(I), false, + TemplateParams->getDepth(), UsedParameters); break; } case TPOC_Conversion: - ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, + ::MarkUsedTemplateParameters(S, Proto2->getResultType(), false, + TemplateParams->getDepth(), UsedParameters); break; case TPOC_Other: - ::MarkUsedTemplateParameters(S, FD2->getType(), false, UsedParameters); + ::MarkUsedTemplateParameters(S, FD2->getType(), false, + TemplateParams->getDepth(), + UsedParameters); break; } @@ -2065,6 +2093,7 @@ static void MarkUsedTemplateParameters(Sema &SemaRef, const TemplateArgument &TemplateArg, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used); /// \brief Mark the template parameters that are used by the given @@ -2073,6 +2102,7 @@ static void MarkUsedTemplateParameters(Sema &SemaRef, const Expr *E, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to // find other occurrences of template parameters. @@ -2085,7 +2115,8 @@ MarkUsedTemplateParameters(Sema &SemaRef, if (!NTTP) return; - Used[NTTP->getIndex()] = true; + if (NTTP->getDepth() == Depth) + Used[NTTP->getIndex()] = true; } /// \brief Mark the template parameters that are used by the given @@ -2094,13 +2125,15 @@ static void MarkUsedTemplateParameters(Sema &SemaRef, NestedNameSpecifier *NNS, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { if (!NNS) return; - MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Used); + MarkUsedTemplateParameters(SemaRef, NNS->getPrefix(), OnlyDeduced, Depth, + Used); MarkUsedTemplateParameters(SemaRef, QualType(NNS->getAsType(), 0), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); } /// \brief Mark the template parameters that are used by the given @@ -2109,16 +2142,20 @@ static void MarkUsedTemplateParameters(Sema &SemaRef, TemplateName Name, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { if (TemplateDecl *Template = Name.getAsTemplateDecl()) { if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Template)) - Used[TTP->getIndex()] = true; + = dyn_cast<TemplateTemplateParmDecl>(Template)) { + if (TTP->getDepth() == Depth) + Used[TTP->getIndex()] = true; + } return; } if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) - MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, Used); + MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, + Depth, Used); } /// \brief Mark the template parameters that are used by the given @@ -2126,6 +2163,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, static void MarkUsedTemplateParameters(Sema &SemaRef, QualType T, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { if (T.isNull()) return; @@ -2140,6 +2178,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, MarkUsedTemplateParameters(SemaRef, cast<PointerType>(T)->getPointeeType(), OnlyDeduced, + Depth, Used); break; @@ -2147,6 +2186,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, MarkUsedTemplateParameters(SemaRef, cast<BlockPointerType>(T)->getPointeeType(), OnlyDeduced, + Depth, Used); break; @@ -2155,69 +2195,74 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, MarkUsedTemplateParameters(SemaRef, cast<ReferenceType>(T)->getPointeeType(), OnlyDeduced, + Depth, Used); break; case Type::MemberPointer: { const MemberPointerType *MemPtr = cast<MemberPointerType>(T.getTypePtr()); MarkUsedTemplateParameters(SemaRef, MemPtr->getPointeeType(), OnlyDeduced, - Used); + Depth, Used); MarkUsedTemplateParameters(SemaRef, QualType(MemPtr->getClass(), 0), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); break; } case Type::DependentSizedArray: MarkUsedTemplateParameters(SemaRef, cast<DependentSizedArrayType>(T)->getSizeExpr(), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); // Fall through to check the element type case Type::ConstantArray: case Type::IncompleteArray: MarkUsedTemplateParameters(SemaRef, cast<ArrayType>(T)->getElementType(), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); break; case Type::Vector: case Type::ExtVector: MarkUsedTemplateParameters(SemaRef, cast<VectorType>(T)->getElementType(), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); break; case Type::DependentSizedExtVector: { const DependentSizedExtVectorType *VecType = cast<DependentSizedExtVectorType>(T); MarkUsedTemplateParameters(SemaRef, VecType->getElementType(), OnlyDeduced, - Used); + Depth, Used); MarkUsedTemplateParameters(SemaRef, VecType->getSizeExpr(), OnlyDeduced, - Used); + Depth, Used); break; } case Type::FunctionProto: { const FunctionProtoType *Proto = cast<FunctionProtoType>(T); MarkUsedTemplateParameters(SemaRef, Proto->getResultType(), OnlyDeduced, - Used); + Depth, Used); for (unsigned I = 0, N = Proto->getNumArgs(); I != N; ++I) MarkUsedTemplateParameters(SemaRef, Proto->getArgType(I), OnlyDeduced, - Used); + Depth, Used); break; } - case Type::TemplateTypeParm: - Used[cast<TemplateTypeParmType>(T)->getIndex()] = true; + case Type::TemplateTypeParm: { + const TemplateTypeParmType *TTP = cast<TemplateTypeParmType>(T); + if (TTP->getDepth() == Depth) + Used[TTP->getIndex()] = true; break; + } case Type::TemplateSpecialization: { const TemplateSpecializationType *Spec = cast<TemplateSpecializationType>(T); MarkUsedTemplateParameters(SemaRef, Spec->getTemplateName(), OnlyDeduced, - Used); + Depth, Used); for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) - MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Used); + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); break; } @@ -2225,14 +2270,14 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, if (!OnlyDeduced) MarkUsedTemplateParameters(SemaRef, cast<ComplexType>(T)->getElementType(), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); break; case Type::Typename: if (!OnlyDeduced) MarkUsedTemplateParameters(SemaRef, cast<TypenameType>(T)->getQualifier(), - OnlyDeduced, Used); + OnlyDeduced, Depth, Used); break; // None of these types have any template parameters in them. @@ -2259,6 +2304,7 @@ static void MarkUsedTemplateParameters(Sema &SemaRef, const TemplateArgument &TemplateArg, bool OnlyDeduced, + unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { switch (TemplateArg.getKind()) { case TemplateArgument::Null: @@ -2267,25 +2313,27 @@ MarkUsedTemplateParameters(Sema &SemaRef, case TemplateArgument::Type: MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsType(), OnlyDeduced, - Used); + Depth, Used); break; case TemplateArgument::Declaration: if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) - Used[TTP->getIndex()] = true; + = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) { + if (TTP->getDepth() == Depth) + Used[TTP->getIndex()] = true; + } break; case TemplateArgument::Expression: MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsExpr(), OnlyDeduced, - Used); + Depth, Used); break; case TemplateArgument::Pack: for (TemplateArgument::pack_iterator P = TemplateArg.pack_begin(), PEnd = TemplateArg.pack_end(); P != PEnd; ++P) - MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Used); + MarkUsedTemplateParameters(SemaRef, *P, OnlyDeduced, Depth, Used); break; } } @@ -2301,10 +2349,11 @@ MarkUsedTemplateParameters(Sema &SemaRef, /// deduced. void Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, - bool OnlyDeduced, + bool OnlyDeduced, unsigned Depth, llvm::SmallVectorImpl<bool> &Used) { for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, Used); + ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, + Depth, Used); } /// \brief Marks all of the template parameters that will be deduced by a @@ -2319,5 +2368,5 @@ void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(), - true, Deduced); + true, TemplateParams->getDepth(), Deduced); } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 53d1580..dfe37d8 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -392,6 +392,13 @@ namespace { /// \brief Returns the name of the entity being instantiated, if any. DeclarationName getBaseEntity() { return Entity; } + /// \brief Sets the "base" location and entity when that + /// information is known based on another transformation. + void setBase(SourceLocation Loc, DeclarationName Entity) { + this->Loc = Loc; + this->Entity = Entity; + } + /// \brief Transform the given declaration by instantiating a reference to /// this declaration. Decl *TransformDecl(Decl *D); @@ -415,8 +422,10 @@ namespace { /// elaborated type. QualType RebuildElaboratedType(QualType T, ElaboratedType::TagKind Tag); - Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E); - Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E); + Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E, + bool isAddressOfOperand); + Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E, + bool isAddressOfOperand); /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. @@ -528,7 +537,8 @@ TemplateInstantiator::RebuildElaboratedType(QualType T, } Sema::OwningExprResult -TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { +TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E, + bool isAddressOfOperand) { if (!E->isTypeDependent()) return SemaRef.Owned(E->Retain()); @@ -551,62 +561,64 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { } Sema::OwningExprResult -TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { +TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, + bool isAddressOfOperand) { // FIXME: Clean this up a bit NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { - if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) { - assert(false && "Cannot reduce non-type template parameter depth yet"); - return getSema().ExprError(); - } - - // If the corresponding template argument is NULL or non-existent, it's - // because we are performing instantiation from explicitly-specified - // template arguments in a function template, but there were some - // arguments left unspecified. - if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), - NTTP->getPosition())) - return SemaRef.Owned(E->Retain()); - - const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), - NTTP->getPosition()); - - // The template argument itself might be an expression, in which - // case we just return that expression. - if (Arg.getKind() == TemplateArgument::Expression) - return SemaRef.Owned(Arg.getAsExpr()->Retain()); - - if (Arg.getKind() == TemplateArgument::Declaration) { - ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); - - VD = cast_or_null<ValueDecl>( + if (NTTP->getDepth() < TemplateArgs.getNumLevels()) { + + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), + NTTP->getPosition())) + return SemaRef.Owned(E->Retain()); + + const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), + NTTP->getPosition()); + + // The template argument itself might be an expression, in which + // case we just return that expression. + if (Arg.getKind() == TemplateArgument::Expression) + return SemaRef.Owned(Arg.getAsExpr()->Retain()); + + if (Arg.getKind() == TemplateArgument::Declaration) { + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + + VD = cast_or_null<ValueDecl>( getSema().FindInstantiatedDecl(VD, TemplateArgs)); - if (!VD) - return SemaRef.ExprError(); + if (!VD) + return SemaRef.ExprError(); - return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), - /*FIXME:*/false, /*FIXME:*/false); - } + return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), + /*FIXME:*/false, /*FIXME:*/false); + } - assert(Arg.getKind() == TemplateArgument::Integral); - QualType T = Arg.getIntegralType(); - if (T->isCharType() || T->isWideCharType()) - return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( - Arg.getAsIntegral()->getZExtValue(), - T->isWideCharType(), - T, - E->getSourceRange().getBegin())); - 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(), + assert(Arg.getKind() == TemplateArgument::Integral); + QualType T = Arg.getIntegralType(); + if (T->isCharType() || T->isWideCharType()) + return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( + Arg.getAsIntegral()->getZExtValue(), + T->isWideCharType(), T, E->getSourceRange().getBegin())); + 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, + E->getSourceRange().getBegin())); + } + + // We have a non-type template parameter that isn't fully substituted; + // FindInstantiatedDecl will find it in the local instantiation scope. } NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D, TemplateArgs); @@ -618,11 +630,22 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? InstD = InstD->getUnderlyingDecl(); - // FIXME: nested-name-specifier for QualifiedDeclRefExpr + CXXScopeSpec SS; + NestedNameSpecifier *Qualifier = 0; + if (E->getQualifier()) { + Qualifier = TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + + SS.setScopeRep(Qualifier); + SS.setRange(E->getQualifierRange()); + } + return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, /*FIXME:*/false, - /*FIXME:*/0, - /*FIXME:*/false); + &SS, + isAddressOfOperand); } QualType @@ -838,6 +861,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, = Instantiation->getMemberSpecializationInfo()) { MSInfo->setTemplateSpecializationKind(TSK); MSInfo->setPointOfInstantiation(PointOfInstantiation); + } else if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Instantiation)) { + Spec->setTemplateSpecializationKind(TSK); + Spec->setPointOfInstantiation(PointOfInstantiation); } InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation); @@ -892,18 +919,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, if (!Invalid) Consumer.HandleTagDeclDefinition(Instantiation); - // If this is an explicit instantiation, instantiate our members, too. - if (!Invalid && TSK != TSK_ImplicitInstantiation) { - Inst.Clear(); - InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs, - TSK); - } - return Invalid; } bool Sema::InstantiateClassTemplateSpecialization( + SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK, bool Complain) { @@ -921,10 +942,6 @@ Sema::InstantiateClassTemplateSpecialization( // declaration (C++0x [temp.explicit]p10); go ahead and perform the // explicit instantiation. ClassTemplateSpec->setSpecializationKind(TSK); - InstantiateClassTemplateSpecializationMembers( - /*FIXME?*/ClassTemplateSpec->getPointOfInstantiation(), - ClassTemplateSpec, - TSK); return false; } @@ -969,62 +986,72 @@ Sema::InstantiateClassTemplateSpecialization( } } - if (Matched.size() == 1) { - // -- If exactly one matching specialization is found, the - // instantiation is generated from that specialization. - Pattern = Matched[0].first; - ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second); - } else if (Matched.size() > 1) { - // -- If more than one matching specialization is found, the - // partial order rules (14.5.4.2) are used to determine - // whether one of the specializations is more specialized - // than the others. If none of the specializations is more - // specialized than all of the other matching - // specializations, then the use of the class template is - // ambiguous and the program is ill-formed. + if (Matched.size() >= 1) { llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); - for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, - PEnd = Matched.end(); - P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->first, Best->first) - == P->first) - Best = P; - } - - // Determine if the best partial specialization is more specialized than - // the others. - bool Ambiguous = false; - for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), - PEnd = Matched.end(); - P != PEnd; ++P) { - if (P != Best && - getMoreSpecializedPartialSpecialization(P->first, Best->first) - != Best->first) { - Ambiguous = true; - break; + if (Matched.size() == 1) { + // -- If exactly one matching specialization is found, the + // instantiation is generated from that specialization. + // We don't need to do anything for this. + } else { + // -- If more than one matching specialization is found, the + // partial order rules (14.5.4.2) are used to determine + // whether one of the specializations is more specialized + // than the others. If none of the specializations is more + // specialized than all of the other matching + // specializations, then the use of the class template is + // ambiguous and the program is ill-formed. + for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, + PEnd = Matched.end(); + P != PEnd; ++P) { + if (getMoreSpecializedPartialSpecialization(P->first, Best->first) + == P->first) + Best = P; } - } - - if (Ambiguous) { - // Partial ordering did not produce a clear winner. Complain. - ClassTemplateSpec->setInvalidDecl(); - Diag(ClassTemplateSpec->getPointOfInstantiation(), - diag::err_partial_spec_ordering_ambiguous) - << ClassTemplateSpec; - // Print the matching partial specializations. + // Determine if the best partial specialization is more specialized than + // the others. + bool Ambiguous = false; for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), PEnd = Matched.end(); - P != PEnd; ++P) - Diag(P->first->getLocation(), diag::note_partial_spec_match) - << getTemplateArgumentBindingsText(P->first->getTemplateParameters(), - *P->second); - - return true; + P != PEnd; ++P) { + if (P != Best && + getMoreSpecializedPartialSpecialization(P->first, Best->first) + != Best->first) { + Ambiguous = true; + break; + } + } + + if (Ambiguous) { + // Partial ordering did not produce a clear winner. Complain. + ClassTemplateSpec->setInvalidDecl(); + Diag(PointOfInstantiation, diag::err_partial_spec_ordering_ambiguous) + << ClassTemplateSpec; + + // Print the matching partial specializations. + for (llvm::SmallVector<MatchResult, 4>::iterator P = Matched.begin(), + PEnd = Matched.end(); + P != PEnd; ++P) + Diag(P->first->getLocation(), diag::note_partial_spec_match) + << getTemplateArgumentBindingsText(P->first->getTemplateParameters(), + *P->second); + + return true; + } } // Instantiate using the best class template partial specialization. - Pattern = Best->first; + ClassTemplatePartialSpecializationDecl *OrigPartialSpec = Best->first; + while (OrigPartialSpec->getInstantiatedFromMember()) { + // If we've found an explicit specialization of this class template, + // stop here and use that as the pattern. + if (OrigPartialSpec->isMemberSpecialization()) + break; + + OrigPartialSpec = OrigPartialSpec->getInstantiatedFromMember(); + } + + Pattern = OrigPartialSpec; ClassTemplateSpec->setInstantiationOf(Best->first, Best->second); } else { // -- If no matches are found, the instantiation is generated @@ -1042,12 +1069,9 @@ Sema::InstantiateClassTemplateSpecialization( Pattern = OrigTemplate->getTemplatedDecl(); } - // Note that this is an instantiation. - ClassTemplateSpec->setSpecializationKind(TSK); - - bool Result = InstantiateClass(ClassTemplateSpec->getPointOfInstantiation(), - ClassTemplateSpec, Pattern, - getTemplateInstantiationArgs(ClassTemplateSpec), + bool Result = InstantiateClass(PointOfInstantiation, ClassTemplateSpec, + Pattern, + getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain); @@ -1071,48 +1095,112 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, for (DeclContext::decl_iterator D = Instantiation->decls_begin(), DEnd = Instantiation->decls_end(); D != DEnd; ++D) { + bool SuppressNew = false; if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) { - if (Function->getInstantiatedFromMemberFunction()) { - // If this member was explicitly specialized, do nothing. - if (Function->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization) + if (FunctionDecl *Pattern + = Function->getInstantiatedFromMemberFunction()) { + MemberSpecializationInfo *MSInfo + = Function->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Function, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) + continue; + + if (Function->getBody()) continue; + + if (TSK == TSK_ExplicitInstantiationDefinition) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (!Pattern->getBody()) + continue; - Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + + InstantiateFunctionDefinition(PointOfInstantiation, Function); + } else { + Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } } - - if (!Function->getBody() && TSK == TSK_ExplicitInstantiationDefinition) - InstantiateFunctionDefinition(PointOfInstantiation, Function); } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) { if (Var->isStaticDataMember()) { - // If this member was explicitly specialized, do nothing. - if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Var, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) continue; - Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); - - if (TSK == TSK_ExplicitInstantiationDefinition) + if (TSK == TSK_ExplicitInstantiationDefinition) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (!Var->getInstantiatedFromStaticDataMember() + ->getOutOfLineDefinition()) + continue; + + Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var); - } + } else { + Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } + } } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) { if (Record->isInjectedClassName()) continue; - assert(Record->getInstantiatedFromMemberClass() && - "Missing instantiated-from-template information"); - - // If this member was explicitly specialized, do nothing. - if (Record->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information?"); + if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK, + Record, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew) || + SuppressNew) continue; - if (!Record->getDefinition(Context)) - InstantiateClass(PointOfInstantiation, Record, - Record->getInstantiatedFromMemberClass(), + CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); + assert(Pattern && "Missing instantiated-from-template information"); + + if (!Record->getDefinition(Context)) { + if (!Pattern->getDefinition(Context)) { + // C++0x [temp.explicit]p8: + // An explicit instantiation definition that names a class template + // specialization explicitly instantiates the class template + // specialization and is only an explicit instantiation definition + // of members whose definition is visible at the point of + // instantiation. + if (TSK == TSK_ExplicitInstantiationDeclaration) { + MSInfo->setTemplateSpecializationKind(TSK); + MSInfo->setPointOfInstantiation(PointOfInstantiation); + } + + continue; + } + + InstantiateClass(PointOfInstantiation, Record, Pattern, TemplateArgs, TSK); + } - InstantiateClassMembers(PointOfInstantiation, Record, TemplateArgs, - TSK); + Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); + if (Pattern) + InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, + TSK); } } } @@ -1178,9 +1266,10 @@ Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc, return Instantiator.TransformTemplateName(Name); } -TemplateArgument Sema::Subst(TemplateArgument Arg, - const MultiLevelTemplateArgumentList &TemplateArgs) { +bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output, + const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(), DeclarationName()); - return Instantiator.TransformTemplateArgument(Arg); + + return Instantiator.TransformTemplateArgument(Input, Output); } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index be4adbc..7288ae2 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -56,12 +56,12 @@ namespace { Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); Decl *VisitCXXConversionDecl(CXXConversionDecl *D); ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D); - Decl *VisitOriginalParmVarDecl(OriginalParmVarDecl *D); Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); Decl *VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D); Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); + Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D); // Base case. FIXME: Remove once we can instantiate everything. @@ -82,6 +82,10 @@ namespace { TemplateParameterList * SubstTemplateParams(TemplateParameterList *List); + + bool InstantiateClassTemplatePartialSpecialization( + ClassTemplateDecl *ClassTemplate, + ClassTemplatePartialSpecializationDecl *PartialSpec); }; } @@ -99,20 +103,20 @@ TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { bool Invalid = false; - QualType T = D->getUnderlyingType(); - if (T->isDependentType()) { - T = SemaRef.SubstType(T, TemplateArgs, - D->getLocation(), D->getDeclName()); - if (T.isNull()) { + DeclaratorInfo *DI = D->getTypeDeclaratorInfo(); + if (DI->getType()->isDependentType()) { + DI = SemaRef.SubstType(DI, TemplateArgs, + D->getLocation(), D->getDeclName()); + if (!DI) { Invalid = true; - T = SemaRef.Context.IntTy; + DI = SemaRef.Context.getTrivialDeclaratorInfo(SemaRef.Context.IntTy); } } // Create the new typedef TypedefDecl *Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier(), T); + D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); @@ -161,7 +165,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // which they were instantiated. if (Var->isStaticDataMember()) SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, - TSK_ImplicitInstantiation); + TSK_ImplicitInstantiation); if (D->getInit()) { OwningExprResult Init @@ -389,7 +393,25 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { return 0; } +namespace { + class SortDeclByLocation { + SourceManager &SourceMgr; + + public: + explicit SortDeclByLocation(SourceManager &SourceMgr) + : SourceMgr(SourceMgr) { } + + bool operator()(const Decl *X, const Decl *Y) const { + return SourceMgr.isBeforeInTranslationUnit(X->getLocation(), + Y->getLocation()); + } + }; +} + Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { + // Create a local instantiation scope for this class template, which + // will contain the instantiations of the template parameters. + Sema::LocalInstantiationScope Scope(SemaRef); TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) @@ -406,32 +428,83 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { = ClassTemplateDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), InstParams, RecordInst, 0); RecordInst->setDescribedClassTemplate(Inst); - Inst->setAccess(D->getAccess()); + if (D->getFriendObjectKind()) + Inst->setObjectOfFriendDecl(true); + else + Inst->setAccess(D->getAccess()); Inst->setInstantiatedFromMemberTemplate(D); // Trigger creation of the type for the instantiation. SemaRef.Context.getTypeDeclType(RecordInst); + // Finish handling of friends. + if (Inst->getFriendObjectKind()) { + return Inst; + } + Owner->addDecl(Inst); + + // First, we sort the partial specializations by location, so + // that we instantiate them in the order they were declared. + llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator + P = D->getPartialSpecializations().begin(), + PEnd = D->getPartialSpecializations().end(); + P != PEnd; ++P) + PartialSpecs.push_back(&*P); + std::sort(PartialSpecs.begin(), PartialSpecs.end(), + SortDeclByLocation(SemaRef.SourceMgr)); + + // Instantiate all of the partial specializations of this member class + // template. + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) + InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]); + return Inst; } Decl * TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( ClassTemplatePartialSpecializationDecl *D) { - assert(false &&"Partial specializations of member templates are unsupported"); + ClassTemplateDecl *ClassTemplate = D->getSpecializedTemplate(); + + // Lookup the already-instantiated declaration in the instantiation + // of the class template and return that. + DeclContext::lookup_result Found + = Owner->lookup(ClassTemplate->getDeclName()); + if (Found.first == Found.second) + return 0; + + ClassTemplateDecl *InstClassTemplate + = dyn_cast<ClassTemplateDecl>(*Found.first); + if (!InstClassTemplate) + return 0; + + Decl *DCanon = D->getCanonicalDecl(); + for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator + P = InstClassTemplate->getPartialSpecializations().begin(), + PEnd = InstClassTemplate->getPartialSpecializations().end(); + P != PEnd; ++P) { + if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) + return &*P; + } + return 0; } Decl * TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { - // FIXME: Dig out the out-of-line definition of this function template? - + // Create a local instantiation scope for this function template, which + // will contain the instantiations of the template parameters and then get + // merged with the local instantiation scope for the function template + // itself. + Sema::LocalInstantiationScope Scope(SemaRef); + TemplateParameterList *TempParams = D->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) return NULL; - + FunctionDecl *Instantiated = 0; if (CXXMethodDecl *DMethod = dyn_cast<CXXMethodDecl>(D->getTemplatedDecl())) Instantiated = cast_or_null<FunctionDecl>(VisitCXXMethodDecl(DMethod, @@ -516,7 +589,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { return Info->Function; } - Sema::LocalInstantiationScope Scope(SemaRef); + Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0); llvm::SmallVector<ParmVarDecl *, 4> Params; QualType T = SubstFunctionType(D, Params); @@ -530,7 +603,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getDeclName(), T, D->getDeclaratorInfo(), D->getStorageClass(), - D->isInline(), D->hasWrittenPrototype()); + D->isInlineSpecified(), D->hasWrittenPrototype()); Function->setLexicalDeclContext(Owner); // Attach the parameters @@ -645,7 +718,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return Info->Function; } - Sema::LocalInstantiationScope Scope(SemaRef); + Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0); llvm::SmallVector<ParmVarDecl *, 4> Params; QualType T = SubstFunctionType(D, Params); @@ -666,14 +739,14 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Name, T, Constructor->getDeclaratorInfo(), Constructor->isExplicit(), - Constructor->isInline(), false); + Constructor->isInlineSpecified(), false); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { QualType ClassTy = SemaRef.Context.getTypeDeclType(Record); Name = SemaRef.Context.DeclarationNames.getCXXDestructorName( SemaRef.Context.getCanonicalType(ClassTy)); Method = CXXDestructorDecl::Create(SemaRef.Context, Record, Destructor->getLocation(), Name, - T, Destructor->isInline(), false); + T, Destructor->isInlineSpecified(), false); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { CanQualType ConvTy = SemaRef.Context.getCanonicalType( @@ -683,12 +756,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Method = CXXConversionDecl::Create(SemaRef.Context, Record, Conversion->getLocation(), Name, T, Conversion->getDeclaratorInfo(), - Conversion->isInline(), + Conversion->isInlineSpecified(), Conversion->isExplicit()); } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, D->getLocation(), D->getDeclName(), T, D->getDeclaratorInfo(), - D->isStatic(), D->isInline()); + D->isStatic(), D->isInlineSpecified()); } if (TemplateParams) { @@ -776,24 +849,27 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - QualType OrigT = SemaRef.SubstType(D->getOriginalType(), TemplateArgs, - D->getLocation(), D->getDeclName()); - if (OrigT.isNull()) + QualType T; + DeclaratorInfo *DI = D->getDeclaratorInfo(); + if (DI) { + DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), + D->getDeclName()); + if (DI) T = DI->getType(); + } else { + T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), + D->getDeclName()); + DI = 0; + } + + if (T.isNull()) return 0; - QualType T = SemaRef.adjustParameterType(OrigT); + T = SemaRef.adjustParameterType(T); // Allocate the parameter - ParmVarDecl *Param = 0; - if (T == OrigT) - Param = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(), - D->getIdentifier(), T, D->getDeclaratorInfo(), - D->getStorageClass(), 0); - else - Param = OriginalParmVarDecl::Create(SemaRef.Context, Owner, - D->getLocation(), D->getIdentifier(), - T, D->getDeclaratorInfo(), OrigT, - D->getStorageClass(), 0); + ParmVarDecl *Param + = ParmVarDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), T, DI, D->getStorageClass(), 0); // Mark the default argument as being uninstantiated. if (D->hasUninstantiatedDefaultArg()) @@ -808,15 +884,6 @@ ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { return Param; } -Decl * -TemplateDeclInstantiator::VisitOriginalParmVarDecl(OriginalParmVarDecl *D) { - // Since parameter types can decay either before or after - // instantiation, we simply treat OriginalParmVarDecls as - // ParmVarDecls the same way, and create one or the other depending - // on what happens after template instantiation. - return VisitParmVarDecl(D); -} - Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *D) { // TODO: don't always clone when decls are refcounted. @@ -826,26 +893,71 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), - TTPT->getDepth(), TTPT->getIndex(), + TTPT->getDepth() - 1, TTPT->getIndex(), TTPT->getName(), D->wasDeclaredWithTypename(), D->isParameterPack()); + // FIXME: Do we actually want to perform substitution here? I don't think + // we do. if (D->hasDefaultArgument()) { - QualType DefaultPattern = D->getDefaultArgument(); - QualType DefaultInst + DeclaratorInfo *DefaultPattern = D->getDefaultArgumentInfo(); + DeclaratorInfo *DefaultInst = SemaRef.SubstType(DefaultPattern, TemplateArgs, D->getDefaultArgumentLoc(), D->getDeclName()); Inst->setDefaultArgument(DefaultInst, - D->getDefaultArgumentLoc(), D->defaultArgumentWasInherited() /* preserve? */); } + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return Inst; } +Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( + NonTypeTemplateParmDecl *D) { + // Substitute into the type of the non-type template parameter. + QualType T; + DeclaratorInfo *DI = D->getDeclaratorInfo(); + if (DI) { + DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), + D->getDeclName()); + if (DI) T = DI->getType(); + } else { + T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), + D->getDeclName()); + DI = 0; + } + if (T.isNull()) + return 0; + + // Check that this type is acceptable for a non-type template parameter. + bool Invalid = false; + T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation()); + if (T.isNull()) { + T = SemaRef.Context.IntTy; + Invalid = true; + } + + NonTypeTemplateParmDecl *Param + = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getDepth() - 1, D->getPosition(), + D->getIdentifier(), T, DI); + if (Invalid) + Param->setInvalidDecl(); + + Param->setDefaultArgument(D->getDefaultArgument()); + + // Introduce this template parameter's instantiation into the instantiation + // scope. + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Param); + return Param; +} + Decl * TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { NestedNameSpecifier *NNS = @@ -913,6 +1025,136 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { return InstL; } +/// \brief Instantiate the declaration of a class template partial +/// specialization. +/// +/// \param ClassTemplate the (instantiated) class template that is partially +// specialized by the instantiation of \p PartialSpec. +/// +/// \param PartialSpec the (uninstantiated) class template partial +/// specialization that we are instantiating. +/// +/// \returns true if there was an error, false otherwise. +bool +TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( + ClassTemplateDecl *ClassTemplate, + ClassTemplatePartialSpecializationDecl *PartialSpec) { + // Create a local instantiation scope for this class template partial + // specialization, which will contain the instantiations of the template + // parameters. + Sema::LocalInstantiationScope Scope(SemaRef); + + // Substitute into the template parameters of the class template partial + // specialization. + TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return true; + + // Substitute into the template arguments of the class template partial + // specialization. + const TemplateArgumentLoc *PartialSpecTemplateArgs + = PartialSpec->getTemplateArgsAsWritten(); + unsigned N = PartialSpec->getNumTemplateArgsAsWritten(); + + llvm::SmallVector<TemplateArgumentLoc, 4> InstTemplateArgs(N); + for (unsigned I = 0; I != N; ++I) { + if (SemaRef.Subst(PartialSpecTemplateArgs[I], InstTemplateArgs[I], + TemplateArgs)) + return true; + } + + + // Check that the template argument list is well-formed for this + // class template. + TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), + InstTemplateArgs.size()); + if (SemaRef.CheckTemplateArgumentList(ClassTemplate, + PartialSpec->getLocation(), + /*FIXME:*/PartialSpec->getLocation(), + InstTemplateArgs.data(), + InstTemplateArgs.size(), + /*FIXME:*/PartialSpec->getLocation(), + false, + Converted)) + return true; + + // Figure out where to insert this class template partial specialization + // in the member template's set of class template partial specializations. + llvm::FoldingSetNodeID ID; + ClassTemplatePartialSpecializationDecl::Profile(ID, + Converted.getFlatArguments(), + Converted.flatSize(), + SemaRef.Context); + void *InsertPos = 0; + ClassTemplateSpecializationDecl *PrevDecl + = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, + InsertPos); + + // Build the canonical type that describes the converted template + // arguments of the class template partial specialization. + QualType CanonType + = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), + Converted.getFlatArguments(), + Converted.flatSize()); + + // Build the fully-sugared type for this class template + // specialization as the user wrote in the specialization + // itself. This means that we'll pretty-print the type retrieved + // from the specialization's declaration the way that the user + // actually wrote the specialization, rather than formatting the + // name based on the "canonical" representation used to store the + // template arguments in the specialization. + QualType WrittenTy + = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), + InstTemplateArgs.data(), + InstTemplateArgs.size(), + CanonType); + + if (PrevDecl) { + // We've already seen a partial specialization with the same template + // parameters and template arguments. This can happen, for example, when + // substituting the outer template arguments ends up causing two + // class template partial specializations of a member class template + // to have identical forms, e.g., + // + // template<typename T, typename U> + // struct Outer { + // template<typename X, typename Y> struct Inner; + // template<typename Y> struct Inner<T, Y>; + // template<typename Y> struct Inner<U, Y>; + // }; + // + // Outer<int, int> outer; // error: the partial specializations of Inner + // // have the same signature. + SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) + << WrittenTy; + SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) + << SemaRef.Context.getTypeDeclType(PrevDecl); + return true; + } + + + // Create the class template partial specialization declaration. + ClassTemplatePartialSpecializationDecl *InstPartialSpec + = ClassTemplatePartialSpecializationDecl::Create(SemaRef.Context, Owner, + PartialSpec->getLocation(), + InstParams, + ClassTemplate, + Converted, + InstTemplateArgs.data(), + InstTemplateArgs.size(), + 0); + InstPartialSpec->setInstantiatedFromMember(PartialSpec); + InstPartialSpec->setTypeAsWritten(WrittenTy); + + // Add this partial specialization to the set of class template partial + // specializations. + ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec, + InsertPos); + return false; +} + /// \brief Does substitution on the type of the given function, including /// all of the function parameters. /// @@ -1065,20 +1307,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, return; // Find the function body that we'll be substituting. - const FunctionDecl *PatternDecl = 0; - if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) { - while (Primary->getInstantiatedFromMemberTemplate()) { - // If we have hit a point where the user provided a specialization of - // this template, we're done looking. - if (Primary->isMemberSpecialization()) - break; - - Primary = Primary->getInstantiatedFromMemberTemplate(); - } - - PatternDecl = Primary->getTemplatedDecl(); - } else - PatternDecl = Function->getInstantiatedFromMemberFunction(); + const FunctionDecl *PatternDecl = Function->getTemplateInstantiationPattern(); Stmt *Pattern = 0; if (PatternDecl) Pattern = PatternDecl->getBody(PatternDecl); @@ -1108,7 +1337,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // to which they refer. if (Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDeclaration && - PatternDecl->isOutOfLine() && !PatternDecl->isInline()) + !PatternDecl->isInlined()) return; InstantiatingTemplate Inst(*this, PointOfInstantiation, Function); @@ -1199,24 +1428,17 @@ void Sema::InstantiateStaticDataMemberDefinition( // Find the out-of-line definition of this static data member. VarDecl *Def = Var->getInstantiatedFromStaticDataMember(); - bool FoundOutOfLineDef = false; assert(Def && "This data member was not instantiated from a template?"); - assert(Def->isStaticDataMember() && "Not a static data member?"); - for (VarDecl::redecl_iterator RD = Def->redecls_begin(), - RDEnd = Def->redecls_end(); - RD != RDEnd; ++RD) { - if (RD->getLexicalDeclContext()->isFileContext()) { - Def = *RD; - FoundOutOfLineDef = true; - } - } + assert(Def->isStaticDataMember() && "Not a static data member?"); + Def = Def->getOutOfLineDefinition(); - if (!FoundOutOfLineDef) { + if (!Def) { // We did not find an out-of-line definition of this static data member, // so we won't perform any instantiation. Rather, we rely on the user to // instantiate this definition (or provide a specialization for it) in // another translation unit. if (DefinitionRequired) { + Def = Var->getInstantiatedFromStaticDataMember(); Diag(PointOfInstantiation, diag::err_explicit_instantiation_undefined_member) << 2 << Var->getDeclName() << Var->getDeclContext(); @@ -1379,6 +1601,22 @@ static bool isInstantiationOf(FunctionTemplateDecl *Pattern, return false; } +static bool +isInstantiationOf(ClassTemplatePartialSpecializationDecl *Pattern, + ClassTemplatePartialSpecializationDecl *Instance) { + Pattern + = cast<ClassTemplatePartialSpecializationDecl>(Pattern->getCanonicalDecl()); + do { + Instance = cast<ClassTemplatePartialSpecializationDecl>( + Instance->getCanonicalDecl()); + if (Pattern == Instance) + return true; + Instance = Instance->getInstantiatedFromMember(); + } while (Instance); + + return false; +} + static bool isInstantiationOf(CXXRecordDecl *Pattern, CXXRecordDecl *Instance) { Pattern = Pattern->getCanonicalDecl(); @@ -1469,6 +1707,11 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (FunctionTemplateDecl *Temp = dyn_cast<FunctionTemplateDecl>(Other)) return isInstantiationOf(cast<FunctionTemplateDecl>(D), Temp); + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>(Other)) + return isInstantiationOf(cast<ClassTemplatePartialSpecializationDecl>(D), + PartialSpec); + if (FieldDecl *Field = dyn_cast<FieldDecl>(Other)) { if (!Field->getDeclName()) { // This is an unnamed field. @@ -1550,7 +1793,9 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, } DeclContext *ParentDC = D->getDeclContext(); - if (isa<ParmVarDecl>(D) || ParentDC->isFunctionOrMethod()) { + if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || + isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || + ParentDC->isFunctionOrMethod()) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D)); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 49f7119..0003b1b 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -31,36 +31,58 @@ using namespace clang; /// C++ [dcl.fct]p3). The adjusted parameter type is returned. QualType Sema::adjustParameterType(QualType T) { // C99 6.7.5.3p7: - if (T->isArrayType()) { - // C99 6.7.5.3p7: - // A declaration of a parameter as "array of type" shall be - // adjusted to "qualified pointer to type", where the type - // qualifiers (if any) are those specified within the [ and ] of - // the array type derivation. + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + if (T->isArrayType()) return Context.getArrayDecayedType(T); - } else if (T->isFunctionType()) - // C99 6.7.5.3p8: - // A declaration of a parameter as "function returning type" - // shall be adjusted to "pointer to function returning type", as - // in 6.3.2.1. + + // C99 6.7.5.3p8: + // A declaration of a parameter as "function returning type" + // shall be adjusted to "pointer to function returning type", as + // in 6.3.2.1. + if (T->isFunctionType()) return Context.getPointerType(T); return T; } + + +/// isOmittedBlockReturnType - Return true if this declarator is missing a +/// return type because this is a omitted return type on a block literal. +static bool isOmittedBlockReturnType(const Declarator &D) { + if (D.getContext() != Declarator::BlockLiteralContext || + D.getDeclSpec().hasTypeSpecifier()) + return false; + + if (D.getNumTypeObjects() == 0) + return true; // ^{ ... } + + if (D.getNumTypeObjects() == 1 && + D.getTypeObject(0).Kind == DeclaratorChunk::Function) + return true; // ^(int X, float Y) { ... } + + return false; +} + /// \brief Convert the specified declspec to the appropriate type /// object. -/// \param DS the declaration specifiers -/// \param DeclLoc The location of the declarator identifier or invalid if none. +/// \param D the declarator containing the declaration specifier. /// \returns The type described by the declaration specifiers. This function /// never returns null. -QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, - SourceLocation DeclLoc, - bool &isInvalid) { +static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ // FIXME: Should move the logic from DeclSpec::Finish to here for validity // checking. - QualType Result; + const DeclSpec &DS = TheDeclarator.getDeclSpec(); + SourceLocation DeclLoc = TheDeclarator.getIdentifierLoc(); + if (DeclLoc.isInvalid()) + DeclLoc = DS.getSourceRange().getBegin(); + + ASTContext &Context = TheSema.Context; + QualType Result; switch (DS.getTypeSpecType()) { case DeclSpec::TST_void: Result = Context.VoidTy; @@ -80,13 +102,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified) Result = Context.WCharTy; else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) { - Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType()); Result = Context.getSignedWCharType(); } else { assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned && "Unknown TSS value"); - Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) + TheSema.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec) << DS.getSpecifierName(DS.getTypeSpecType()); Result = Context.getUnsignedWCharType(); } @@ -109,6 +131,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, DS.getNumProtocolQualifiers()); break; } + + // If this is a missing declspec in a block literal return context, then it + // is inferred from the return statements inside the block. + if (isOmittedBlockReturnType(TheDeclarator)) { + Result = Context.DependentTy; + break; + } // Unspecified typespec defaults to int in C90. However, the C90 grammar // [C90 6.5] only allows a decl-spec if there was *some* type-specifier, @@ -117,13 +146,11 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // allowed to be completely missing a declspec. This is handled in the // parser already though by it pretending to have seen an 'int' in this // case. - if (getLangOptions().ImplicitInt) { + if (TheSema.getLangOptions().ImplicitInt) { // In C89 mode, we only warn if there is a completely missing declspec // when one is not allowed. if (DS.isEmpty()) { - if (DeclLoc.isInvalid()) - DeclLoc = DS.getSourceRange().getBegin(); - Diag(DeclLoc, diag::ext_missing_declspec) + TheSema.Diag(DeclLoc, diag::ext_missing_declspec) << DS.getSourceRange() << CodeModificationHint::CreateInsertion(DS.getSourceRange().getBegin(), "int"); @@ -134,19 +161,17 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // specifiers in each declaration, and in the specifier-qualifier list in // each struct declaration and type name." // FIXME: Does Microsoft really have the implicit int extension in C++? - if (DeclLoc.isInvalid()) - DeclLoc = DS.getSourceRange().getBegin(); - - if (getLangOptions().CPlusPlus && !getLangOptions().Microsoft) { - Diag(DeclLoc, diag::err_missing_type_specifier) + if (TheSema.getLangOptions().CPlusPlus && + !TheSema.getLangOptions().Microsoft) { + TheSema.Diag(DeclLoc, diag::err_missing_type_specifier) << DS.getSourceRange(); // When this occurs in C++ code, often something is very broken with the // value being declared, poison it as invalid so we don't get chains of // errors. - isInvalid = true; + TheDeclarator.setInvalidType(true); } else { - Diag(DeclLoc, diag::ext_missing_type_specifier) + TheSema.Diag(DeclLoc, diag::ext_missing_type_specifier) << DS.getSourceRange(); } } @@ -158,14 +183,28 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, case DeclSpec::TSW_unspecified: Result = Context.IntTy; break; case DeclSpec::TSW_short: Result = Context.ShortTy; break; case DeclSpec::TSW_long: Result = Context.LongTy; break; - case DeclSpec::TSW_longlong: Result = Context.LongLongTy; break; + case DeclSpec::TSW_longlong: + Result = Context.LongLongTy; + + // long long is a C99 feature. + if (!TheSema.getLangOptions().C99 && + !TheSema.getLangOptions().CPlusPlus0x) + TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + break; } } else { switch (DS.getTypeSpecWidth()) { case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break; case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break; case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break; - case DeclSpec::TSW_longlong: Result =Context.UnsignedLongLongTy; break; + case DeclSpec::TSW_longlong: + Result = Context.UnsignedLongLongTy; + + // long long is a C99 feature. + if (!TheSema.getLangOptions().C99 && + !TheSema.getLangOptions().CPlusPlus0x) + TheSema.Diag(DS.getTypeSpecWidthLoc(), diag::ext_longlong); + break; } } break; @@ -181,44 +220,47 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, case DeclSpec::TST_decimal32: // _Decimal32 case DeclSpec::TST_decimal64: // _Decimal64 case DeclSpec::TST_decimal128: // _Decimal128 - Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); + TheSema.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported); Result = Context.IntTy; - isInvalid = true; + TheDeclarator.setInvalidType(true); break; case DeclSpec::TST_class: case DeclSpec::TST_enum: case DeclSpec::TST_union: case DeclSpec::TST_struct: { - Decl *D = static_cast<Decl *>(DS.getTypeRep()); + TypeDecl *D = cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep())); if (!D) { // This can happen in C++ with ambiguous lookups. Result = Context.IntTy; - isInvalid = true; + TheDeclarator.setInvalidType(true); break; } + // If the type is deprecated or unavailable, diagnose it. + TheSema.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeLoc()); + assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && - DS.getTypeSpecSign() == 0 && - "Can't handle qualifiers on typedef names yet!"); + DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!"); + // TypeQuals handled by caller. - Result = Context.getTypeDeclType(cast<TypeDecl>(D)); + Result = Context.getTypeDeclType(D); // In C++, make an ElaboratedType. - if (getLangOptions().CPlusPlus) { + if (TheSema.getLangOptions().CPlusPlus) { TagDecl::TagKind Tag = TagDecl::getTagKindForTypeSpec(DS.getTypeSpecType()); Result = Context.getElaboratedType(Result, Tag); } if (D->isInvalidDecl()) - isInvalid = true; + TheDeclarator.setInvalidType(true); break; } case DeclSpec::TST_typename: { assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 && DS.getTypeSpecSign() == 0 && "Can't handle qualifiers on typedef names yet!"); - Result = GetTypeFromParser(DS.getTypeRep()); + Result = TheSema.GetTypeFromParser(DS.getTypeRep()); if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { if (const ObjCInterfaceType * @@ -240,31 +282,22 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy, (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers()); else if (Result->isObjCClassType()) { - if (DeclLoc.isInvalid()) - DeclLoc = DS.getSourceRange().getBegin(); // Class<protocol-list> Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy, (ObjCProtocolDecl**)PQ, DS.getNumProtocolQualifiers()); } else { - if (DeclLoc.isInvalid()) - DeclLoc = DS.getSourceRange().getBegin(); - Diag(DeclLoc, diag::err_invalid_protocol_qualifiers) + TheSema.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers) << DS.getSourceRange(); - isInvalid = true; + TheDeclarator.setInvalidType(true); } } - // If this is a reference to an invalid typedef, propagate the invalidity. - if (TypedefType *TDT = dyn_cast<TypedefType>(Result)) - if (TDT->getDecl()->isInvalidDecl()) - isInvalid = true; - // TypeQuals handled by caller. break; } case DeclSpec::TST_typeofType: // FIXME: Preserve type source info. - Result = GetTypeFromParser(DS.getTypeRep()); + Result = TheSema.GetTypeFromParser(DS.getTypeRep()); assert(!Result.isNull() && "Didn't get a type for typeof?"); // TypeQuals handled by caller. Result = Context.getTypeOfType(Result); @@ -280,10 +313,10 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Expr *E = static_cast<Expr *>(DS.getTypeRep()); assert(E && "Didn't get an expression for decltype?"); // TypeQuals handled by caller. - Result = BuildDecltypeType(E); + Result = TheSema.BuildDecltypeType(E); if (Result.isNull()) { Result = Context.IntTy; - isInvalid = true; + TheDeclarator.setInvalidType(true); } break; } @@ -295,14 +328,14 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, case DeclSpec::TST_error: Result = Context.IntTy; - isInvalid = true; + TheDeclarator.setInvalidType(true); break; } // Handle complex types. if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) { - if (getLangOptions().Freestanding) - Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); + if (TheSema.getLangOptions().Freestanding) + TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); Result = Context.getComplexType(Result); } @@ -312,7 +345,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // See if there are any attributes on the declspec that apply to the type (as // opposed to the decl). if (const AttributeList *AL = DS.getAttributes()) - ProcessTypeAttributeList(Result, AL); + TheSema.ProcessTypeAttributeList(Result, AL); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -329,13 +362,13 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, // If we have a pointer or reference, the pointee must have an object // incomplete type. if (!EltTy->isIncompleteOrObjectType()) { - Diag(DS.getRestrictSpecLoc(), + TheSema.Diag(DS.getRestrictSpecLoc(), diag::err_typecheck_invalid_restrict_invalid_pointee) << EltTy << DS.getSourceRange(); TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. } } else { - Diag(DS.getRestrictSpecLoc(), + TheSema.Diag(DS.getRestrictSpecLoc(), diag::err_typecheck_invalid_restrict_not_pointer) << Result << DS.getSourceRange(); TypeQuals &= ~DeclSpec::TQ_restrict; // Remove the restrict qualifier. @@ -357,7 +390,7 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, "Has CVR quals but not C, V, or R?"); Loc = DS.getRestrictSpecLoc(); } - Diag(Loc, diag::warn_typecheck_function_qualifiers) + TheSema.Diag(Loc, diag::warn_typecheck_function_qualifiers) << Result << DS.getSourceRange(); } @@ -407,7 +440,7 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, if (T->isReferenceType()) { // C++ 8.3.2p4: There shall be no ... pointers to references ... Diag(Loc, diag::err_illegal_decl_pointer_to_reference) - << getPrintableNameForEntity(Entity); + << getPrintableNameForEntity(Entity) << T; return QualType(); } @@ -535,14 +568,14 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, if (T->isFunctionType()) { Diag(Loc, diag::err_illegal_decl_array_of_functions) - << getPrintableNameForEntity(Entity); + << getPrintableNameForEntity(Entity) << T; return QualType(); } // C++ 8.3.2p4: There shall be no ... arrays of references ... if (T->isReferenceType()) { Diag(Loc, diag::err_illegal_decl_array_of_references) - << getPrintableNameForEntity(Entity); + << getPrintableNameForEntity(Entity) << T; return QualType(); } @@ -746,7 +779,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, // with reference type, or "cv void." if (T->isReferenceType()) { Diag(Loc, diag::err_illegal_decl_mempointer_to_reference) - << (Entity? Entity.getAsString() : "type name"); + << (Entity? Entity.getAsString() : "type name") << T; return QualType(); } @@ -805,6 +838,11 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) { QualType QT = QualType::getFromOpaquePtr(Ty); + if (QT.isNull()) { + if (DInfo) *DInfo = 0; + return QualType(); + } + DeclaratorInfo *DI = 0; if (LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) { QT = LIT->getType(); @@ -816,58 +854,31 @@ QualType Sema::GetTypeFromParser(TypeTy *Ty, DeclaratorInfo **DInfo) { } /// GetTypeForDeclarator - Convert the type for the specified -/// declarator to Type instances. Skip the outermost Skip type -/// objects. +/// declarator to Type instances. /// /// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq /// owns the declaration of a type (e.g., the definition of a struct /// type), then *OwnedDecl will receive the owned declaration. QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, - DeclaratorInfo **DInfo, unsigned Skip, + DeclaratorInfo **DInfo, TagDecl **OwnedDecl) { - bool OmittedReturnType = false; - - if (D.getContext() == Declarator::BlockLiteralContext - && Skip == 0 - && !D.getDeclSpec().hasTypeSpecifier() - && (D.getNumTypeObjects() == 0 - || (D.getNumTypeObjects() == 1 - && D.getTypeObject(0).Kind == DeclaratorChunk::Function))) - OmittedReturnType = true; - - // long long is a C99 feature. - if (!getLangOptions().C99 && !getLangOptions().CPlusPlus0x && - D.getDeclSpec().getTypeSpecWidth() == DeclSpec::TSW_longlong) - Diag(D.getDeclSpec().getTypeSpecWidthLoc(), diag::ext_longlong); - // Determine the type of the declarator. Not all forms of declarator // have a type. QualType T; - switch (D.getKind()) { - case Declarator::DK_Abstract: - case Declarator::DK_Normal: - case Declarator::DK_Operator: - case Declarator::DK_TemplateId: { - const DeclSpec &DS = D.getDeclSpec(); - if (OmittedReturnType) { - // We default to a dependent type initially. Can be modified by - // the first return statement. - T = Context.DependentTy; - } else { - bool isInvalid = false; - T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid); - if (isInvalid) - D.setInvalidType(true); - else if (OwnedDecl && DS.isTypeSpecOwned()) - *OwnedDecl = cast<TagDecl>((Decl *)DS.getTypeRep()); - } + switch (D.getName().getKind()) { + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_TemplateId: + T = ConvertDeclSpecToType(D, *this); + + if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned()) + *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep()); break; - } - case Declarator::DK_Constructor: - case Declarator::DK_Destructor: - case Declarator::DK_Conversion: + case UnqualifiedId::IK_ConstructorName: + case UnqualifiedId::IK_DestructorName: + case UnqualifiedId::IK_ConversionFunctionId: // Constructors and destructors don't have return types. Use // "void" instead. Conversion operators will check their return // types separately. @@ -926,8 +937,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). - for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) { - DeclaratorChunk &DeclType = D.getTypeObject(e-i-1+Skip); + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { + DeclaratorChunk &DeclType = D.getTypeObject(e-i-1); switch (DeclType.Kind) { default: assert(0 && "Unknown decltype!"); case DeclaratorChunk::BlockPointer: @@ -1190,7 +1201,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (getLangOptions().CPlusPlus && T->isFunctionType()) { const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>(); - assert(FnTy && "Why oh why is there not a FunctionProtoType here ?"); + assert(FnTy && "Why oh why is there not a FunctionProtoType here?"); // C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type // for a nonstatic member function, the function type to which a pointer @@ -1224,7 +1235,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.isInvalidType()) *DInfo = 0; else - *DInfo = GetDeclaratorInfoForDeclarator(D, T, Skip); + *DInfo = GetDeclaratorInfoForDeclarator(D, T); } return T; @@ -1289,6 +1300,21 @@ namespace { Visit(TL.getBaseTypeLoc()); } } + void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) { + DeclaratorInfo *DInfo = 0; + Sema::GetTypeFromParser(DS.getTypeRep(), &DInfo); + + // If we got no declarator info from previous Sema routines, + // just fill with the typespec loc. + if (!DInfo) { + TL.initialize(DS.getTypeSpecTypeLoc()); + return; + } + + TemplateSpecializationTypeLoc OldTL = + cast<TemplateSpecializationTypeLoc>(DInfo->getTypeLoc()); + TL.copy(OldTL); + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. TL.initialize(DS.getTypeSpecTypeLoc()); @@ -1366,11 +1392,11 @@ namespace { /// /// \param T QualType referring to the type as written in source code. DeclaratorInfo * -Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) { +Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T) { DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T); UnqualTypeLoc CurrTL = DInfo->getTypeLoc().getUnqualifiedLoc(); - for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) { + for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL); CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -1463,7 +1489,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { DeclaratorInfo *DInfo = 0; TagDecl *OwnedTag = 0; - QualType T = GetTypeForDeclarator(D, S, &DInfo, /*Skip=*/0, &OwnedTag); + QualType T = GetTypeForDeclarator(D, S, &DInfo, &OwnedTag); if (D.isInvalidType()) return true; @@ -1655,13 +1681,10 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, if (const RecordType *Record = T->getAs<RecordType>()) { if (ClassTemplateSpecializationDecl *ClassTemplateSpec = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { - if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) { - if (Loc.isValid()) - ClassTemplateSpec->setPointOfInstantiation(Loc); - return InstantiateClassTemplateSpecialization(ClassTemplateSpec, + if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared) + return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec, TSK_ImplicitInstantiation, /*Complain=*/diag != 0); - } } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Record->getDecl())) { if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) { @@ -1669,13 +1692,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, assert(MSInfo && "Missing member specialization information?"); // This record was instantiated from a class within a template. if (MSInfo->getTemplateSpecializationKind() - != TSK_ExplicitSpecialization) { - MSInfo->setPointOfInstantiation(Loc); + != TSK_ExplicitSpecialization) return InstantiateClass(Loc, Rec, Pattern, getTemplateInstantiationArgs(Rec), TSK_ImplicitInstantiation, /*Complain=*/diag != 0); - } } } } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7e0972f..5713da9 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -290,23 +290,43 @@ public: /// declaration stored within the template argument and constructs a /// new template argument from the transformed result. Subclasses may /// override this function to provide alternate behavior. - TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg); + /// + /// Returns true if there was an error. + bool TransformTemplateArgument(const TemplateArgumentLoc &Input, + TemplateArgumentLoc &Output); + + /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument. + void InventTemplateArgumentLoc(const TemplateArgument &Arg, + TemplateArgumentLoc &ArgLoc); + + /// \brief Fakes up a DeclaratorInfo for a type. + DeclaratorInfo *InventDeclaratorInfo(QualType T) { + return SemaRef.Context.getTrivialDeclaratorInfo(T, + getDerived().getBaseLocation()); + } #define ABSTRACT_TYPELOC(CLASS, PARENT) #define TYPELOC(CLASS, PARENT) \ QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); #include "clang/AST/TypeLocNodes.def" + QualType TransformReferenceType(TypeLocBuilder &TLB, ReferenceTypeLoc TL); + QualType TransformTemplateSpecializationType(const TemplateSpecializationType *T, QualType ObjectType); + + QualType + TransformTemplateSpecializationType(TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL, + QualType ObjectType); OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr); #define STMT(Node, Parent) \ OwningStmtResult Transform##Node(Node *S); #define EXPR(Node, Parent) \ - OwningExprResult Transform##Node(Node *E); + OwningExprResult Transform##Node(Node *E, bool isAddressOfOperand); #define ABSTRACT_EXPR(Node, Parent) #include "clang/AST/StmtNodes.def" @@ -314,35 +334,37 @@ public: /// /// By default, performs semantic analysis when building the pointer type. /// Subclasses may override this routine to provide different behavior. - QualType RebuildPointerType(QualType PointeeType); + QualType RebuildPointerType(QualType PointeeType, SourceLocation Sigil); /// \brief Build a new block pointer type given its pointee type. /// /// By default, performs semantic analysis when building the block pointer /// type. Subclasses may override this routine to provide different behavior. - QualType RebuildBlockPointerType(QualType PointeeType); + QualType RebuildBlockPointerType(QualType PointeeType, SourceLocation Sigil); - /// \brief Build a new lvalue reference type given the type it references. + /// \brief Build a new reference type given the type it references. /// - /// By default, performs semantic analysis when building the lvalue reference - /// type. Subclasses may override this routine to provide different behavior. - QualType RebuildLValueReferenceType(QualType ReferentType); - - /// \brief Build a new rvalue reference type given the type it references. + /// By default, performs semantic analysis when building the + /// reference type. Subclasses may override this routine to provide + /// different behavior. /// - /// By default, performs semantic analysis when building the rvalue reference - /// type. Subclasses may override this routine to provide different behavior. - QualType RebuildRValueReferenceType(QualType ReferentType); + /// \param LValue whether the type was written with an lvalue sigil + /// or an rvalue sigil. + QualType RebuildReferenceType(QualType ReferentType, + bool LValue, + SourceLocation Sigil); /// \brief Build a new member pointer type given the pointee type and the /// class type it refers into. /// /// By default, performs semantic analysis when building the member pointer /// type. Subclasses may override this routine to provide different behavior. - QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType); + QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType, + SourceLocation Sigil); /// \brief Build a new Objective C object pointer type. - QualType RebuildObjCObjectPointerType(QualType PointeeType); + QualType RebuildObjCObjectPointerType(QualType PointeeType, + SourceLocation Sigil); /// \brief Build a new array type given the element type, size /// modifier, size of the array (if known), size expression, and index type @@ -366,7 +388,8 @@ public: QualType RebuildConstantArrayType(QualType ElementType, ArrayType::ArraySizeModifier SizeMod, const llvm::APInt &Size, - unsigned IndexTypeQuals); + unsigned IndexTypeQuals, + SourceRange BracketsRange); /// \brief Build a new incomplete array type given the element type, size /// modifier, and index type qualifiers. @@ -375,7 +398,8 @@ public: /// Subclasses may override this routine to provide different behavior. QualType RebuildIncompleteArrayType(QualType ElementType, ArrayType::ArraySizeModifier SizeMod, - unsigned IndexTypeQuals); + unsigned IndexTypeQuals, + SourceRange BracketsRange); /// \brief Build a new variable-length array type given the element type, /// size modifier, size expression, and index type qualifiers. @@ -478,8 +502,11 @@ public: /// specialization type. Subclasses may override this routine to provide /// different behavior. QualType RebuildTemplateSpecializationType(TemplateName Template, - const TemplateArgument *Args, - unsigned NumArgs); + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + SourceLocation RAngleLoc); /// \brief Build a new qualified name type. /// @@ -509,9 +536,9 @@ public: /// (or qualified name type). Subclasses may override this routine to provide /// different behavior. QualType RebuildTypenameType(NestedNameSpecifier *NNS, - const IdentifierInfo *Id) { - return SemaRef.CheckTypenameType(NNS, *Id, - SourceRange(getDerived().getBaseLocation())); + const IdentifierInfo *Id, + SourceRange SR) { + return SemaRef.CheckTypenameType(NNS, *Id, SR); } /// \brief Build a new nested-name-specifier given the prefix and an @@ -578,7 +605,17 @@ public: const IdentifierInfo &II, QualType ObjectType); - + /// \brief Build a new template name given a nested name specifier and the + /// overloaded operator name that is referred to as a template. + /// + /// By default, performs semantic analysis to determine whether the name can + /// be resolved to a specific template, then builds the appropriate kind of + /// template name. Subclasses may override this routine to provide different + /// behavior. + TemplateName RebuildTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator, + QualType ObjectType); + /// \brief Build a new compound statement. /// /// By default, performs semantic analysis to build the new statement. @@ -781,11 +818,17 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildDeclRefExpr(NamedDecl *ND, SourceLocation Loc) { + OwningExprResult RebuildDeclRefExpr(NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + NamedDecl *ND, SourceLocation Loc, + bool isAddressOfOperand) { + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + SS.setRange(QualifierRange); return getSema().BuildDeclarationNameExpr(Loc, ND, /*FIXME:*/false, - /*SS=*/0, - /*FIXME:*/false); + &SS, + isAddressOfOperand); } /// \brief Build a new expression in parentheses. @@ -841,9 +884,10 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildSizeOfAlignOf(QualType T, SourceLocation OpLoc, + OwningExprResult RebuildSizeOfAlignOf(DeclaratorInfo *DInfo, + SourceLocation OpLoc, bool isSizeOf, SourceRange R) { - return getSema().CreateSizeOfAlignOfExpr(T, OpLoc, isSizeOf, R); + return getSema().CreateSizeOfAlignOfExpr(DInfo, OpLoc, isSizeOf, R); } /// \brief Build a new sizeof or alignof expression with an expression @@ -1002,9 +1046,9 @@ public: SourceLocation OpLoc, SourceLocation AccessorLoc, IdentifierInfo &Accessor) { - return getSema().ActOnMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, + return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OpLoc, tok::period, AccessorLoc, - Accessor, + DeclarationName(&Accessor), /*FIXME?*/Sema::DeclPtrTy::make((Decl*)0)); } @@ -1392,26 +1436,6 @@ public: T.getAsOpaquePtr(), RParenLoc); } - /// \brief Build a new qualified declaration reference expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildQualifiedDeclRefExpr(NestedNameSpecifier *NNS, - SourceRange QualifierRange, - NamedDecl *ND, - SourceLocation Location, - bool IsAddressOfOperand) { - CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(NNS); - return getSema().ActOnDeclarationNameExpr(/*Scope=*/0, - Location, - ND->getDeclName(), - /*Trailing lparen=*/false, - &SS, - IsAddressOfOperand); - } - /// \brief Build a new (previously unresolved) declaration reference /// expression. /// @@ -1442,7 +1466,7 @@ public: TemplateName Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - TemplateArgument *TemplateArgs, + TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange, @@ -1545,7 +1569,7 @@ public: SourceLocation TemplateNameLoc, NamedDecl *FirstQualifierInScope, SourceLocation LAngleLoc, - const TemplateArgument *TemplateArgs, + const TemplateArgumentLoc *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc) { OwningExprResult Base = move(BaseE); @@ -1556,16 +1580,21 @@ public: SS.setScopeRep(Qualifier); // FIXME: We're going to end up looking up the template based on its name, - // twice! Also, duplicates part of Sema::ActOnMemberTemplateIdReferenceExpr. + // twice! Also, duplicates part of Sema::BuildMemberAccessExpr. DeclarationName Name; if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) Name = ActualTemplate->getDeclName(); else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl()) Name = Ovl->getDeclName(); - else - Name = Template.getAsDependentTemplateName()->getName(); - + else { + DependentTemplateName *DTN = Template.getAsDependentTemplateName(); + if (DTN->isIdentifier()) + Name = DTN->getIdentifier(); + else + Name = SemaRef.Context.DeclarationNames.getCXXOperatorName( + DTN->getOperator()); + } return SemaRef.BuildMemberReferenceExpr(/*Scope=*/0, move(Base), OperatorLoc, OpKind, TemplateNameLoc, Name, true, @@ -1683,7 +1712,8 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E, case Stmt::NoStmtClass: break; #define STMT(Node, Parent) case Stmt::Node##Class: break; #define EXPR(Node, Parent) \ - case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E)); + case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E), \ + isAddressOfOperand); #include "clang/AST/StmtNodes.def" } @@ -1746,6 +1776,7 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS, case NestedNameSpecifier::TypeSpecWithTemplate: case NestedNameSpecifier::TypeSpec: { + TemporaryBase Rebase(*this, Range.getBegin(), DeclarationName()); QualType T = getDerived().TransformType(QualType(NNS->getAsType(), 0)); if (T.isNull()) return 0; @@ -1860,7 +1891,12 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name, ObjectType.isNull()) return Name; - return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType); + if (DTN->isIdentifier()) + return getDerived().RebuildTemplateName(NNS, *DTN->getIdentifier(), + ObjectType); + + return getDerived().RebuildTemplateName(NNS, DTN->getOperator(), + ObjectType); } if (TemplateDecl *Template = Name.getAsTemplateDecl()) { @@ -1891,25 +1927,80 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name, } template<typename Derived> -TemplateArgument -TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) { +void TreeTransform<Derived>::InventTemplateArgumentLoc( + const TemplateArgument &Arg, + TemplateArgumentLoc &Output) { + SourceLocation Loc = getDerived().getBaseLocation(); + switch (Arg.getKind()) { + case TemplateArgument::Null: + llvm::llvm_unreachable("null template argument in TreeTransform"); + break; + + case TemplateArgument::Type: + Output = TemplateArgumentLoc(Arg, + SemaRef.Context.getTrivialDeclaratorInfo(Arg.getAsType(), Loc)); + + break; + + case TemplateArgument::Expression: + Output = TemplateArgumentLoc(Arg, Arg.getAsExpr()); + break; + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::Pack: + Output = TemplateArgumentLoc(Arg, TemplateArgumentLocInfo()); + break; + } +} + +template<typename Derived> +bool TreeTransform<Derived>::TransformTemplateArgument( + const TemplateArgumentLoc &Input, + TemplateArgumentLoc &Output) { + const TemplateArgument &Arg = Input.getArgument(); switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: - return Arg; + Output = Input; + return false; case TemplateArgument::Type: { - QualType T = getDerived().TransformType(Arg.getAsType()); - if (T.isNull()) - return TemplateArgument(); - return TemplateArgument(Arg.getLocation(), T); + DeclaratorInfo *DI = Input.getSourceDeclaratorInfo(); + if (DI == NULL) + DI = InventDeclaratorInfo(Input.getArgument().getAsType()); + + DI = getDerived().TransformType(DI); + if (!DI) return true; + + Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + return false; } case TemplateArgument::Declaration: { + // FIXME: we should never have to transform one of these. + DeclarationName Name; + if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) + Name = ND->getDeclName(); + TemporaryBase Rebase(*this, SourceLocation(), Name); Decl *D = getDerived().TransformDecl(Arg.getAsDecl()); - if (!D) - return TemplateArgument(); - return TemplateArgument(Arg.getLocation(), D); + if (!D) return true; + + Expr *SourceExpr = Input.getSourceDeclExpression(); + if (SourceExpr) { + EnterExpressionEvaluationContext Unevaluated(getSema(), + Action::Unevaluated); + Sema::OwningExprResult E = getDerived().TransformExpr(SourceExpr); + if (E.isInvalid()) + SourceExpr = NULL; + else { + SourceExpr = E.takeAs<Expr>(); + SourceExpr->Retain(); + } + } + + Output = TemplateArgumentLoc(TemplateArgument(D), SourceExpr); + return false; } case TemplateArgument::Expression: { @@ -1917,10 +2008,17 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) { EnterExpressionEvaluationContext Unevaluated(getSema(), Action::Unevaluated); - Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr()); - if (E.isInvalid()) - return TemplateArgument(); - return TemplateArgument(E.takeAs<Expr>()); + Expr *InputExpr = Input.getSourceExpression(); + if (!InputExpr) InputExpr = Input.getArgument().getAsExpr(); + + Sema::OwningExprResult E + = getDerived().TransformExpr(InputExpr); + if (E.isInvalid()) return true; + + Expr *ETaken = E.takeAs<Expr>(); + ETaken->Retain(); + Output = TemplateArgumentLoc(TemplateArgument(ETaken), ETaken); + return false; } case TemplateArgument::Pack: { @@ -1929,21 +2027,28 @@ TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) { for (TemplateArgument::pack_iterator A = Arg.pack_begin(), AEnd = Arg.pack_end(); A != AEnd; ++A) { - TemplateArgument TA = getDerived().TransformTemplateArgument(*A); - if (TA.isNull()) - return TA; - TransformedArgs.push_back(TA); + // FIXME: preserve source information here when we start + // caring about parameter packs. + + TemplateArgumentLoc InputArg; + TemplateArgumentLoc OutputArg; + getDerived().InventTemplateArgumentLoc(*A, InputArg); + if (getDerived().TransformTemplateArgument(InputArg, OutputArg)) + return true; + + TransformedArgs.push_back(OutputArg.getArgument()); } TemplateArgument Result; Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(), true); - return Result; + Output = TemplateArgumentLoc(Result, Input.getLocInfo()); + return false; } } // Work around bogus GCC warning - return TemplateArgument(); + return true; } //===----------------------------------------------------------------------===// @@ -2048,7 +2153,8 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { QualType Result = TL.getType(); \ if (getDerived().AlwaysRebuild() || \ PointeeType != TL.getPointeeLoc().getType()) { \ - Result = getDerived().Rebuild##TypeClass(PointeeType); \ + Result = getDerived().Rebuild##TypeClass(PointeeType, \ + TL.getSigilLoc()); \ if (Result.isNull()) \ return QualType(); \ } \ @@ -2059,35 +2165,6 @@ QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { return Result; \ } while(0) -// Reference collapsing forces us to transform reference types -// differently from the other pointer-like types. -#define TransformReferenceType(TypeClass) do { \ - QualType PointeeType \ - = getDerived().TransformType(TLB, TL.getPointeeLoc()); \ - if (PointeeType.isNull()) \ - return QualType(); \ - \ - QualType Result = TL.getType(); \ - if (getDerived().AlwaysRebuild() || \ - PointeeType != TL.getPointeeLoc().getType()) { \ - Result = getDerived().Rebuild##TypeClass(PointeeType); \ - if (Result.isNull()) \ - return QualType(); \ - } \ - \ - /* Workaround: rebuild doesn't always change the type */ \ - /* FIXME: avoid losing this location information. */ \ - if (Result == PointeeType) \ - return Result; \ - ReferenceTypeLoc NewTL; \ - if (isa<LValueReferenceType>(Result)) \ - NewTL = TLB.push<LValueReferenceTypeLoc>(Result); \ - else \ - NewTL = TLB.push<RValueReferenceTypeLoc>(Result); \ - NewTL.setSigilLoc(TL.getSigilLoc()); \ - return Result; \ -} while (0) - template<typename Derived> QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB, BuiltinTypeLoc T) { @@ -2121,18 +2198,54 @@ TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB, TransformPointerLikeType(BlockPointerType); } +/// Transforms a reference type. Note that somewhat paradoxically we +/// don't care whether the type itself is an l-value type or an r-value +/// type; we only care if the type was *written* as an l-value type +/// or an r-value type. +template<typename Derived> +QualType +TreeTransform<Derived>::TransformReferenceType(TypeLocBuilder &TLB, + ReferenceTypeLoc TL) { + const ReferenceType *T = TL.getTypePtr(); + + // Note that this works with the pointee-as-written. + QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); + if (PointeeType.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || + PointeeType != T->getPointeeTypeAsWritten()) { + Result = getDerived().RebuildReferenceType(PointeeType, + T->isSpelledAsLValue(), + TL.getSigilLoc()); + if (Result.isNull()) + return QualType(); + } + + // r-value references can be rebuilt as l-value references. + ReferenceTypeLoc NewTL; + if (isa<LValueReferenceType>(Result)) + NewTL = TLB.push<LValueReferenceTypeLoc>(Result); + else + NewTL = TLB.push<RValueReferenceTypeLoc>(Result); + NewTL.setSigilLoc(TL.getSigilLoc()); + + return Result; +} + template<typename Derived> QualType TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB, LValueReferenceTypeLoc TL) { - TransformReferenceType(LValueReferenceType); + return TransformReferenceType(TLB, TL); } template<typename Derived> QualType TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB, RValueReferenceTypeLoc TL) { - TransformReferenceType(RValueReferenceType); + return TransformReferenceType(TLB, TL); } template<typename Derived> @@ -2155,7 +2268,8 @@ TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, if (getDerived().AlwaysRebuild() || PointeeType != T->getPointeeType() || ClassType != QualType(T->getClass(), 0)) { - Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType); + Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType, + TL.getStarLoc()); if (Result.isNull()) return QualType(); } @@ -2181,7 +2295,8 @@ TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB, Result = getDerived().RebuildConstantArrayType(ElementType, T->getSizeModifier(), T->getSize(), - T->getIndexTypeCVRQualifiers()); + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); if (Result.isNull()) return QualType(); } @@ -2214,7 +2329,8 @@ QualType TreeTransform<Derived>::TransformIncompleteArrayType( ElementType != T->getElementType()) { Result = getDerived().RebuildIncompleteArrayType(ElementType, T->getSizeModifier(), - T->getIndexTypeCVRQualifiers()); + T->getIndexTypeCVRQualifiers(), + TL.getBracketsRange()); if (Result.isNull()) return QualType(); } @@ -2254,7 +2370,7 @@ TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, T->getSizeModifier(), move(SizeResult), T->getIndexTypeCVRQualifiers(), - T->getBracketsRange()); + TL.getBracketsRange()); if (Result.isNull()) return QualType(); } @@ -2295,7 +2411,7 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, T->getSizeModifier(), move(SizeResult), T->getIndexTypeCVRQualifiers(), - T->getBracketsRange()); + TL.getBracketsRange()); if (Result.isNull()) return QualType(); } @@ -2331,7 +2447,8 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || - (ElementType != T->getElementType() && Size.get() != T->getSizeExpr())) { + ElementType != T->getElementType() || + Size.get() != T->getSizeExpr()) { Result = getDerived().RebuildDependentSizedExtVectorType(ElementType, move(Size), T->getAttributeLoc()); @@ -2687,46 +2804,76 @@ inline QualType TreeTransform<Derived>::TransformTemplateSpecializationType( TypeLocBuilder &TLB, TemplateSpecializationTypeLoc TL) { - // TODO: figure out how make this work with an ObjectType. - QualType Result - = TransformTemplateSpecializationType(TL.getTypePtr(), QualType()); - if (Result.isNull()) - return QualType(); + return TransformTemplateSpecializationType(TLB, TL, QualType()); +} - TemplateSpecializationTypeLoc NewTL - = TLB.push<TemplateSpecializationTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); +template<typename Derived> +QualType TreeTransform<Derived>::TransformTemplateSpecializationType( + const TemplateSpecializationType *TST, + QualType ObjectType) { + // FIXME: this entire method is a temporary workaround; callers + // should be rewritten to provide real type locs. - return Result; + // Fake up a TemplateSpecializationTypeLoc. + TypeLocBuilder TLB; + TemplateSpecializationTypeLoc TL + = TLB.push<TemplateSpecializationTypeLoc>(QualType(TST, 0)); + + SourceLocation BaseLoc = getDerived().getBaseLocation(); + + TL.setTemplateNameLoc(BaseLoc); + TL.setLAngleLoc(BaseLoc); + TL.setRAngleLoc(BaseLoc); + for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { + const TemplateArgument &TA = TST->getArg(i); + TemplateArgumentLoc TAL; + getDerived().InventTemplateArgumentLoc(TA, TAL); + TL.setArgLocInfo(i, TAL.getLocInfo()); + } + + TypeLocBuilder IgnoredTLB; + return TransformTemplateSpecializationType(IgnoredTLB, TL, ObjectType); } template<typename Derived> QualType TreeTransform<Derived>::TransformTemplateSpecializationType( - const TemplateSpecializationType *T, - QualType ObjectType) { + TypeLocBuilder &TLB, + TemplateSpecializationTypeLoc TL, + QualType ObjectType) { + const TemplateSpecializationType *T = TL.getTypePtr(); + TemplateName Template = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType); if (Template.isNull()) return QualType(); - llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs; - NewTemplateArgs.reserve(T->getNumArgs()); - for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end(); - Arg != ArgEnd; ++Arg) { - TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg); - if (NewArg.isNull()) + llvm::SmallVector<TemplateArgumentLoc, 4> NewTemplateArgs(T->getNumArgs()); + for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) + if (getDerived().TransformTemplateArgument(TL.getArgLoc(i), + NewTemplateArgs[i])) return QualType(); - NewTemplateArgs.push_back(NewArg); - } + // FIXME: maybe don't rebuild if all the template arguments are the same. - // FIXME: early abort if all of the template arguments and such are the - // same. + QualType Result = + getDerived().RebuildTemplateSpecializationType(Template, + TL.getTemplateNameLoc(), + TL.getLAngleLoc(), + NewTemplateArgs.data(), + NewTemplateArgs.size(), + TL.getRAngleLoc()); - // FIXME: We're missing the locations of the template name, '<', and '>'. - return getDerived().RebuildTemplateSpecializationType(Template, - NewTemplateArgs.data(), - NewTemplateArgs.size()); + if (!Result.isNull()) { + TemplateSpecializationTypeLoc NewTL + = TLB.push<TemplateSpecializationTypeLoc>(Result); + NewTL.setTemplateNameLoc(TL.getTemplateNameLoc()); + NewTL.setLAngleLoc(TL.getLAngleLoc()); + NewTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i) + NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo()); + } + + return Result; } template<typename Derived> @@ -2763,9 +2910,12 @@ template<typename Derived> QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL) { TypenameType *T = TL.getTypePtr(); + + /* FIXME: preserve source information better than this */ + SourceRange SR(TL.getNameLoc()); + NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(T->getQualifier(), - SourceRange(/*FIXME:*/getDerived().getBaseLocation())); + = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR); if (!NNS) return QualType(); @@ -2784,7 +2934,7 @@ QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB, Result = getDerived().RebuildTypenameType(NNS, NewTemplateId); } else { - Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier()); + Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), SR); } if (Result.isNull()) return QualType(); @@ -3268,57 +3418,88 @@ TreeTransform<Derived>::TransformCXXTryStmt(CXXTryStmt *S) { //===----------------------------------------------------------------------===// template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E) { +TreeTransform<Derived>::TransformPredefinedExpr(PredefinedExpr *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E) { +TreeTransform<Derived>::TransformDeclRefExpr(DeclRefExpr *E, + bool isAddressOfOperand) { + NestedNameSpecifier *Qualifier = 0; + if (E->getQualifier()) { + Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), + E->getQualifierRange()); + if (!Qualifier) + return SemaRef.ExprError(); + } + NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl())); if (!ND) return SemaRef.ExprError(); - if (!getDerived().AlwaysRebuild() && ND == E->getDecl()) + if (!getDerived().AlwaysRebuild() && + Qualifier == E->getQualifier() && + ND == E->getDecl() && + !E->hasExplicitTemplateArgumentList()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildDeclRefExpr(ND, E->getLocation()); + // FIXME: We're losing the explicit template arguments in this transformation. + + llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs()); + for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], + TransArgs[I])) + return SemaRef.ExprError(); + } + + // FIXME: Pass the qualifier/qualifier range along. + return getDerived().RebuildDeclRefExpr(Qualifier, E->getQualifierRange(), + ND, E->getLocation(), + isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E) { +TreeTransform<Derived>::TransformIntegerLiteral(IntegerLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) { +TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E) { +TreeTransform<Derived>::TransformImaginaryLiteral(ImaginaryLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E) { +TreeTransform<Derived>::TransformStringLiteral(StringLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E) { +TreeTransform<Derived>::TransformCharacterLiteral(CharacterLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { +TreeTransform<Derived>::TransformParenExpr(ParenExpr *E, + bool isAddressOfOperand) { OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -3332,8 +3513,10 @@ TreeTransform<Derived>::TransformParenExpr(ParenExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { - OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); +TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E, + bool isAddressOfOperand) { + OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr(), + E->getOpcode() == UnaryOperator::AddrOf); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -3347,16 +3530,19 @@ TreeTransform<Derived>::TransformUnaryOperator(UnaryOperator *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { +TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, + bool isAddressOfOperand) { if (E->isArgumentType()) { - QualType T = getDerived().TransformType(E->getArgumentType()); - if (T.isNull()) + DeclaratorInfo *OldT = E->getArgumentTypeInfo(); + + DeclaratorInfo *NewT = getDerived().TransformType(OldT); + if (!NewT) return SemaRef.ExprError(); - if (!getDerived().AlwaysRebuild() && T == E->getArgumentType()) + if (!getDerived().AlwaysRebuild() && OldT == NewT) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildSizeOfAlignOf(T, E->getOperatorLoc(), + return getDerived().RebuildSizeOfAlignOf(NewT, E->getOperatorLoc(), E->isSizeOf(), E->getSourceRange()); } @@ -3383,7 +3569,8 @@ TreeTransform<Derived>::TransformSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { +TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E, + bool isAddressOfOperand) { OwningExprResult LHS = getDerived().TransformExpr(E->getLHS()); if (LHS.isInvalid()) return SemaRef.ExprError(); @@ -3406,7 +3593,8 @@ TreeTransform<Derived>::TransformArraySubscriptExpr(ArraySubscriptExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { +TreeTransform<Derived>::TransformCallExpr(CallExpr *E, + bool isAddressOfOperand) { // Transform the callee. OwningExprResult Callee = getDerived().TransformExpr(E->getCallee()); if (Callee.isInvalid()) @@ -3445,7 +3633,8 @@ TreeTransform<Derived>::TransformCallExpr(CallExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { +TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E, + bool isAddressOfOperand) { OwningExprResult Base = getDerived().TransformExpr(E->getBase()); if (Base.isInvalid()) return SemaRef.ExprError(); @@ -3484,14 +3673,16 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCastExpr(CastExpr *E) { +TreeTransform<Derived>::TransformCastExpr(CastExpr *E, + bool isAddressOfOperand) { assert(false && "Cannot transform abstract class"); return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { +TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E, + bool isAddressOfOperand) { OwningExprResult LHS = getDerived().TransformExpr(E->getLHS()); if (LHS.isInvalid()) return SemaRef.ExprError(); @@ -3512,13 +3703,15 @@ TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCompoundAssignOperator( - CompoundAssignOperator *E) { - return getDerived().TransformBinaryOperator(E); + CompoundAssignOperator *E, + bool isAddressOfOperand) { + return getDerived().TransformBinaryOperator(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) { +TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E, + bool isAddressOfOperand) { OwningExprResult Cond = getDerived().TransformExpr(E->getCond()); if (Cond.isInvalid()) return SemaRef.ExprError(); @@ -3546,7 +3739,12 @@ TreeTransform<Derived>::TransformConditionalOperator(ConditionalOperator *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) { +TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E, + bool isAddressOfOperand) { + TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); + + // FIXME: Will we ever have type information here? It seems like we won't, + // so do we even need to transform the type? QualType T = getDerived().TransformType(E->getType()); if (T.isNull()) return SemaRef.ExprError(); @@ -3567,14 +3765,16 @@ TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) { +TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E, + bool isAddressOfOperand) { assert(false && "Cannot transform abstract class"); return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) { +TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E, + bool isAddressOfOperand) { QualType T; { // FIXME: Source location isn't quite accurate. @@ -3603,7 +3803,8 @@ TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) { +TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E, + bool isAddressOfOperand) { QualType T; { // FIXME: Source location isn't quite accurate. @@ -3632,7 +3833,8 @@ TreeTransform<Derived>::TransformCompoundLiteralExpr(CompoundLiteralExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { +TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E, + bool isAddressOfOperand) { OwningExprResult Base = getDerived().TransformExpr(E->getBase()); if (Base.isInvalid()) return SemaRef.ExprError(); @@ -3651,7 +3853,8 @@ TreeTransform<Derived>::TransformExtVectorElementExpr(ExtVectorElementExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { +TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E, + bool isAddressOfOperand) { bool InitChanged = false; ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef); @@ -3673,7 +3876,8 @@ TreeTransform<Derived>::TransformInitListExpr(InitListExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { +TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E, + bool isAddressOfOperand) { Designation Desig; // transform the initializer value @@ -3742,7 +3946,12 @@ TreeTransform<Derived>::TransformDesignatedInitExpr(DesignatedInitExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformImplicitValueInitExpr( - ImplicitValueInitExpr *E) { + ImplicitValueInitExpr *E, + bool isAddressOfOperand) { + TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); + + // FIXME: Will we ever have proper type location here? Will we actually + // need to transform the type? QualType T = getDerived().TransformType(E->getType()); if (T.isNull()) return SemaRef.ExprError(); @@ -3756,7 +3965,8 @@ TreeTransform<Derived>::TransformImplicitValueInitExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) { +TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E, + bool isAddressOfOperand) { // FIXME: Do we want the type as written? QualType T; @@ -3783,7 +3993,8 @@ TreeTransform<Derived>::TransformVAArgExpr(VAArgExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) { +TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E, + bool isAddressOfOperand) { bool ArgumentChanged = false; ASTOwningVector<&ActionBase::DeleteExpr, 4> Inits(SemaRef); for (unsigned I = 0, N = E->getNumExprs(); I != N; ++I) { @@ -3807,13 +4018,16 @@ TreeTransform<Derived>::TransformParenListExpr(ParenListExpr *E) { /// the corresponding label statement by semantic analysis. template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E) { +TreeTransform<Derived>::TransformAddrLabelExpr(AddrLabelExpr *E, + bool isAddressOfOperand) { return getDerived().RebuildAddrLabelExpr(E->getAmpAmpLoc(), E->getLabelLoc(), E->getLabel()); } template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) { +Sema::OwningExprResult +TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E, + bool isAddressOfOperand) { OwningStmtResult SubStmt = getDerived().TransformCompoundStmt(E->getSubStmt(), true); if (SubStmt.isInvalid()) @@ -3830,7 +4044,8 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformStmtExpr(StmtExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) { +TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E, + bool isAddressOfOperand) { QualType T1, T2; { // FIXME: Source location isn't quite accurate. @@ -3856,7 +4071,8 @@ TreeTransform<Derived>::TransformTypesCompatibleExpr(TypesCompatibleExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) { +TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E, + bool isAddressOfOperand) { OwningExprResult Cond = getDerived().TransformExpr(E->getCond()); if (Cond.isInvalid()) return SemaRef.ExprError(); @@ -3882,18 +4098,22 @@ TreeTransform<Derived>::TransformChooseExpr(ChooseExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E) { +TreeTransform<Derived>::TransformGNUNullExpr(GNUNullExpr *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { +TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E, + bool isAddressOfOperand) { OwningExprResult Callee = getDerived().TransformExpr(E->getCallee()); if (Callee.isInvalid()) return SemaRef.ExprError(); - OwningExprResult First = getDerived().TransformExpr(E->getArg(0)); + OwningExprResult First + = getDerived().TransformExpr(E->getArg(0), + E->getNumArgs() == 1 && E->getOperator() == OO_Amp); if (First.isInvalid()) return SemaRef.ExprError(); @@ -3919,13 +4139,15 @@ TreeTransform<Derived>::TransformCXXOperatorCallExpr(CXXOperatorCallExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E) { - return getDerived().TransformCallExpr(E); +TreeTransform<Derived>::TransformCXXMemberCallExpr(CXXMemberCallExpr *E, + bool isAddressOfOperand) { + return getDerived().TransformCallExpr(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { +TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E, + bool isAddressOfOperand) { QualType ExplicitTy; { // FIXME: Source location isn't quite accurate. @@ -3966,33 +4188,38 @@ TreeTransform<Derived>::TransformCXXNamedCastExpr(CXXNamedCastExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E) { - return getDerived().TransformCXXNamedCastExpr(E); +TreeTransform<Derived>::TransformCXXStaticCastExpr(CXXStaticCastExpr *E, + bool isAddressOfOperand) { + return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E) { - return getDerived().TransformCXXNamedCastExpr(E); +TreeTransform<Derived>::TransformCXXDynamicCastExpr(CXXDynamicCastExpr *E, + bool isAddressOfOperand) { + return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXReinterpretCastExpr( - CXXReinterpretCastExpr *E) { - return getDerived().TransformCXXNamedCastExpr(E); + CXXReinterpretCastExpr *E, + bool isAddressOfOperand) { + return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E) { - return getDerived().TransformCXXNamedCastExpr(E); +TreeTransform<Derived>::TransformCXXConstCastExpr(CXXConstCastExpr *E, + bool isAddressOfOperand) { + return getDerived().TransformCXXNamedCastExpr(E, isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXFunctionalCastExpr( - CXXFunctionalCastExpr *E) { + CXXFunctionalCastExpr *E, + bool isAddressOfOperand) { QualType ExplicitTy; { TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName()); @@ -4022,7 +4249,8 @@ TreeTransform<Derived>::TransformCXXFunctionalCastExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { +TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E, + bool isAddressOfOperand) { if (E->isTypeOperand()) { TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); @@ -4062,20 +4290,23 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E) { +TreeTransform<Derived>::TransformCXXBoolLiteralExpr(CXXBoolLiteralExpr *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXNullPtrLiteralExpr( - CXXNullPtrLiteralExpr *E) { + CXXNullPtrLiteralExpr *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { +TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); @@ -4091,7 +4322,8 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) { +TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E, + bool isAddressOfOperand) { OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -4105,7 +4337,8 @@ TreeTransform<Derived>::TransformCXXThrowExpr(CXXThrowExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { +TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E, + bool isAddressOfOperand) { ParmVarDecl *Param = cast_or_null<ParmVarDecl>(getDerived().TransformDecl(E->getParam())); if (!Param) @@ -4120,7 +4353,8 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { +TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); @@ -4139,7 +4373,8 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) { +TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E, + bool isAddressOfOperand) { VarDecl *Var = cast_or_null<VarDecl>(getDerived().TransformDefinition(E->getVarDecl())); if (!Var) @@ -4156,7 +4391,8 @@ TreeTransform<Derived>::TransformCXXConditionDeclExpr(CXXConditionDeclExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { +TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E, + bool isAddressOfOperand) { // Transform the type that we're allocating TemporaryBase Rebase(*this, E->getLocStart(), DeclarationName()); QualType AllocType = getDerived().TransformType(E->getAllocatedType()); @@ -4214,7 +4450,8 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { +TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E, + bool isAddressOfOperand) { OwningExprResult Operand = getDerived().TransformExpr(E->getArgument()); if (Operand.isInvalid()) return SemaRef.ExprError(); @@ -4232,7 +4469,8 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( - CXXPseudoDestructorExpr *E) { + CXXPseudoDestructorExpr *E, + bool isAddressOfOperand) { OwningExprResult Base = getDerived().TransformExpr(E->getBase()); if (Base.isInvalid()) return SemaRef.ExprError(); @@ -4269,14 +4507,16 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr( - UnresolvedFunctionNameExpr *E) { + UnresolvedFunctionNameExpr *E, + bool isAddressOfOperand) { // There is no transformation we can apply to an unresolved function name. return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { +TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); QualType T = getDerived().TransformType(E->getQueriedType()); @@ -4300,34 +4540,9 @@ TreeTransform<Derived>::TransformUnaryTypeTraitExpr(UnaryTypeTraitExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformQualifiedDeclRefExpr(QualifiedDeclRefExpr *E) { - NestedNameSpecifier *NNS - = getDerived().TransformNestedNameSpecifier(E->getQualifier(), - E->getQualifierRange()); - if (!NNS) - return SemaRef.ExprError(); - - NamedDecl *ND - = dyn_cast_or_null<NamedDecl>(getDerived().TransformDecl(E->getDecl())); - if (!ND) - return SemaRef.ExprError(); - - if (!getDerived().AlwaysRebuild() && - NNS == E->getQualifier() && - ND == E->getDecl()) - return SemaRef.Owned(E->Retain()); - - return getDerived().RebuildQualifiedDeclRefExpr(NNS, - E->getQualifierRange(), - ND, - E->getLocation(), - /*FIXME:*/false); -} - -template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformUnresolvedDeclRefExpr( - UnresolvedDeclRefExpr *E) { + UnresolvedDeclRefExpr *E, + bool isAddressOfOperand) { NestedNameSpecifier *NNS = getDerived().TransformNestedNameSpecifier(E->getQualifier(), E->getQualifierRange()); @@ -4348,12 +4563,15 @@ TreeTransform<Derived>::TransformUnresolvedDeclRefExpr( E->getQualifierRange(), Name, E->getLocation(), - /*FIXME:*/false); + isAddressOfOperand); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) { +TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E, + bool isAddressOfOperand) { + TemporaryBase Rebase(*this, E->getTemplateNameLoc(), DeclarationName()); + TemplateName Template = getDerived().TransformTemplateName(E->getTemplateName()); if (Template.isNull()) @@ -4367,14 +4585,11 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) { return SemaRef.ExprError(); } - llvm::SmallVector<TemplateArgument, 4> TransArgs; + llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs()); for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - TemplateArgument TransArg - = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]); - if (TransArg.isNull()) + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], + TransArgs[I])) return SemaRef.ExprError(); - - TransArgs.push_back(TransArg); } // FIXME: Would like to avoid rebuilding if nothing changed, but we can't @@ -4393,7 +4608,8 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { +TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); @@ -4437,7 +4653,8 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { /// must be unique. template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { +TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E, + bool isAddressOfOperand) { OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -4455,7 +4672,8 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXExprWithTemporaries( - CXXExprWithTemporaries *E) { + CXXExprWithTemporaries *E, + bool isAddressOfOperand) { OwningExprResult SubExpr = getDerived().TransformExpr(E->getSubExpr()); if (SubExpr.isInvalid()) return SemaRef.ExprError(); @@ -4468,7 +4686,8 @@ TreeTransform<Derived>::TransformCXXExprWithTemporaries( template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( - CXXTemporaryObjectExpr *E) { + CXXTemporaryObjectExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); if (T.isNull()) @@ -4518,7 +4737,8 @@ TreeTransform<Derived>::TransformCXXTemporaryObjectExpr( template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( - CXXUnresolvedConstructExpr *E) { + CXXUnresolvedConstructExpr *E, + bool isAddressOfOperand) { TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName()); QualType T = getDerived().TransformType(E->getTypeAsWritten()); if (T.isNull()) @@ -4557,7 +4777,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedConstructExpr( template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( - CXXUnresolvedMemberExpr *E) { + CXXUnresolvedMemberExpr *E, + bool isAddressOfOperand) { // Transform the base of the expression. OwningExprResult Base = getDerived().TransformExpr(E->getBase()); if (Base.isInvalid()) @@ -4617,9 +4838,14 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( // FIXME: This is an ugly hack, which forces the same template name to // be looked up multiple times. Yuck! - // FIXME: This also won't work for, e.g., x->template operator+<int> - TemplateName OrigTemplateName - = SemaRef.Context.getDependentTemplateName(0, Name.getAsIdentifierInfo()); + TemporaryBase Rebase(*this, E->getMemberLoc(), DeclarationName()); + TemplateName OrigTemplateName; + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) + OrigTemplateName = SemaRef.Context.getDependentTemplateName(0, II); + else + OrigTemplateName + = SemaRef.Context.getDependentTemplateName(0, + Name.getCXXOverloadedOperator()); TemplateName Template = getDerived().TransformTemplateName(OrigTemplateName, @@ -4627,14 +4853,11 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( if (Template.isNull()) return SemaRef.ExprError(); - llvm::SmallVector<TemplateArgument, 4> TransArgs; + llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs()); for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { - TemplateArgument TransArg - = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]); - if (TransArg.isNull()) + if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I], + TransArgs[I])) return SemaRef.ExprError(); - - TransArgs.push_back(TransArg); } return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base), @@ -4653,13 +4876,15 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E) { +TreeTransform<Derived>::TransformObjCStringLiteral(ObjCStringLiteral *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) { +TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E, + bool isAddressOfOperand) { // FIXME: poor source location TemporaryBase Rebase(*this, E->getAtLoc(), DeclarationName()); QualType EncodedType = getDerived().TransformType(E->getEncodedType()); @@ -4677,7 +4902,8 @@ TreeTransform<Derived>::TransformObjCEncodeExpr(ObjCEncodeExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { +TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4685,13 +4911,15 @@ TreeTransform<Derived>::TransformObjCMessageExpr(ObjCMessageExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E) { +TreeTransform<Derived>::TransformObjCSelectorExpr(ObjCSelectorExpr *E, + bool isAddressOfOperand) { return SemaRef.Owned(E->Retain()); } template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { +TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E, + bool isAddressOfOperand) { ObjCProtocolDecl *Protocol = cast_or_null<ObjCProtocolDecl>( getDerived().TransformDecl(E->getProtocol())); @@ -4712,7 +4940,8 @@ TreeTransform<Derived>::TransformObjCProtocolExpr(ObjCProtocolExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { +TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4720,7 +4949,8 @@ TreeTransform<Derived>::TransformObjCIvarRefExpr(ObjCIvarRefExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { +TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4729,7 +4959,8 @@ TreeTransform<Derived>::TransformObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { + ObjCImplicitSetterGetterRefExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4737,7 +4968,8 @@ TreeTransform<Derived>::TransformObjCImplicitSetterGetterRefExpr( template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) { +TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4745,7 +4977,8 @@ TreeTransform<Derived>::TransformObjCSuperExpr(ObjCSuperExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { +TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform Objective-C expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4753,7 +4986,8 @@ TreeTransform<Derived>::TransformObjCIsaExpr(ObjCIsaExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { +TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E, + bool isAddressOfOperand) { bool ArgumentChanged = false; ASTOwningVector<&ActionBase::DeleteExpr> SubExprs(SemaRef); for (unsigned I = 0, N = E->getNumSubExprs(); I != N; ++I) { @@ -4776,7 +5010,8 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { +TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform block expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4784,7 +5019,8 @@ TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { +TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E, + bool isAddressOfOperand) { // FIXME: Implement this! assert(false && "Cannot transform block-related expressions yet"); return SemaRef.Owned(E->Retain()); @@ -4795,48 +5031,42 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { //===----------------------------------------------------------------------===// template<typename Derived> -QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType) { - return SemaRef.BuildPointerType(PointeeType, Qualifiers(), - getDerived().getBaseLocation(), +QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType, + SourceLocation Star) { + return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star, getDerived().getBaseEntity()); } template<typename Derived> -QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType) { - return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), - getDerived().getBaseLocation(), +QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType, + SourceLocation Star) { + return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star, getDerived().getBaseEntity()); } template<typename Derived> QualType -TreeTransform<Derived>::RebuildLValueReferenceType(QualType ReferentType) { - return SemaRef.BuildReferenceType(ReferentType, true, Qualifiers(), - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); +TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType, + bool WrittenAsLValue, + SourceLocation Sigil) { + return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(), + Sigil, getDerived().getBaseEntity()); } template<typename Derived> QualType -TreeTransform<Derived>::RebuildRValueReferenceType(QualType ReferentType) { - return SemaRef.BuildReferenceType(ReferentType, false, Qualifiers(), - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); -} - -template<typename Derived> -QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, - QualType ClassType) { +TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, + QualType ClassType, + SourceLocation Sigil) { return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(), - getDerived().getBaseLocation(), - getDerived().getBaseEntity()); + Sigil, getDerived().getBaseEntity()); } template<typename Derived> QualType -TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) { - return SemaRef.BuildPointerType(PointeeType, Qualifiers(), - getDerived().getBaseLocation(), +TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType, + SourceLocation Sigil) { + return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Sigil, getDerived().getBaseEntity()); } @@ -4880,18 +5110,20 @@ QualType TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType, ArrayType::ArraySizeModifier SizeMod, const llvm::APInt &Size, - unsigned IndexTypeQuals) { + unsigned IndexTypeQuals, + SourceRange BracketsRange) { return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0, - IndexTypeQuals, SourceRange()); + IndexTypeQuals, BracketsRange); } template<typename Derived> QualType TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType, ArrayType::ArraySizeModifier SizeMod, - unsigned IndexTypeQuals) { + unsigned IndexTypeQuals, + SourceRange BracketsRange) { return getDerived().RebuildArrayType(ElementType, SizeMod, 0, 0, - IndexTypeQuals, SourceRange()); + IndexTypeQuals, BracketsRange); } template<typename Derived> @@ -4980,13 +5212,14 @@ QualType TreeTransform<Derived>::RebuildDecltypeType(ExprArg E) { template<typename Derived> QualType TreeTransform<Derived>::RebuildTemplateSpecializationType( - TemplateName Template, - const TemplateArgument *Args, - unsigned NumArgs) { - // FIXME: Missing source locations for the template name, <, >. - return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(), - SourceLocation(), Args, NumArgs, - SourceLocation()); + TemplateName Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgumentLoc *Args, + unsigned NumArgs, + SourceLocation RAngleLoc) { + return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, LAngleLoc, + Args, NumArgs, RAngleLoc); } template<typename Derived> @@ -5058,16 +5291,37 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, CXXScopeSpec SS; SS.setRange(SourceRange(getDerived().getBaseLocation())); SS.setScopeRep(Qualifier); + UnqualifiedId Name; + Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); return getSema().ActOnDependentTemplateName( /*FIXME:*/getDerived().getBaseLocation(), - II, - /*FIXME:*/getDerived().getBaseLocation(), SS, + Name, ObjectType.getAsOpaquePtr()) .template getAsVal<TemplateName>(); } template<typename Derived> +TemplateName +TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, + OverloadedOperatorKind Operator, + QualType ObjectType) { + CXXScopeSpec SS; + SS.setRange(SourceRange(getDerived().getBaseLocation())); + SS.setScopeRep(Qualifier); + UnqualifiedId Name; + SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. + Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), + Operator, SymbolLocations); + return getSema().ActOnDependentTemplateName( + /*FIXME:*/getDerived().getBaseLocation(), + SS, + Name, + ObjectType.getAsOpaquePtr()) + .template getAsVal<TemplateName>(); +} + +template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, SourceLocation OpLoc, @@ -5076,10 +5330,18 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, ExprArg Second) { Expr *FirstExpr = (Expr *)First.get(); Expr *SecondExpr = (Expr *)Second.get(); + DeclRefExpr *DRE + = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts()); bool isPostIncDec = SecondExpr && (Op == OO_PlusPlus || Op == OO_MinusMinus); // Determine whether this should be a builtin operation. - if (SecondExpr == 0 || isPostIncDec) { + if (Op == OO_Subscript) { + if (!FirstExpr->getType()->isOverloadableType() && + !SecondExpr->getType()->isOverloadableType()) + return getSema().CreateBuiltinArraySubscriptExpr(move(First), + DRE->getLocStart(), + move(Second), OpLoc); + } else if (SecondExpr == 0 || isPostIncDec) { if (!FirstExpr->getType()->isOverloadableType()) { // The argument is not of overloadable type, so try to create a // built-in unary operation. @@ -5109,9 +5371,6 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // used during overload resolution. Sema::FunctionSet Functions; - DeclRefExpr *DRE - = cast<DeclRefExpr>(((Expr *)Callee.get())->IgnoreParenCasts()); - // FIXME: Do we have to check // IsAcceptableNonMemberOperatorCandidate for each of these? for (OverloadIterator F(DRE->getDecl()), FEnd; F != FEnd; ++F) @@ -5122,7 +5381,8 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, unsigned NumArgs = 1 + (SecondExpr != 0); DeclarationName OpName = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); - SemaRef.ArgumentDependentLookup(OpName, Args, NumArgs, Functions); + SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, + Functions); // Create the overloaded operator invocation for unary operators. if (NumArgs == 1 || isPostIncDec) { @@ -5131,6 +5391,10 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, return SemaRef.CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(First)); } + if (Op == OO_Subscript) + return SemaRef.CreateOverloadedArraySubscriptExpr(DRE->getLocStart(), OpLoc, + move(First),move(Second)); + // Create the overloaded operator invocation for binary operators. BinaryOperator::Opcode Opc = BinaryOperator::getOverloadedOpcode(Op); |