aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2009-11-04 15:04:32 +0000
commit51fb8b013e7734b795139f49d3b1f77c539be20a (patch)
tree59e0e47a9831dcf0e21e547927c8ebb7e113bfd1 /lib/Sema
parent73490b890977362d28dd6326843a1ecae413921d (diff)
downloadsrc-51fb8b013e7734b795139f49d3b1f77c539be20a.tar.gz
src-51fb8b013e7734b795139f49d3b1f77c539be20a.zip
Update clang to r86025.vendor/clang/clang-r86025
Notes
Notes: svn path=/vendor/clang/dist/; revision=198893 svn path=/vendor/clang/clang-r86025/; revision=198895; tag=vendor/clang/clang-r86025
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/CodeCompleteConsumer.cpp11
-rw-r--r--lib/Sema/Sema.cpp40
-rw-r--r--lib/Sema/Sema.h217
-rw-r--r--lib/Sema/SemaCXXCast.cpp8
-rw-r--r--lib/Sema/SemaChecking.cpp10
-rw-r--r--lib/Sema/SemaCodeComplete.cpp95
-rw-r--r--lib/Sema/SemaDecl.cpp261
-rw-r--r--lib/Sema/SemaDeclAttr.cpp100
-rw-r--r--lib/Sema/SemaDeclCXX.cpp114
-rw-r--r--lib/Sema/SemaDeclObjC.cpp70
-rw-r--r--lib/Sema/SemaExpr.cpp490
-rw-r--r--lib/Sema/SemaExprCXX.cpp186
-rw-r--r--lib/Sema/SemaLookup.cpp22
-rw-r--r--lib/Sema/SemaOverload.cpp244
-rw-r--r--lib/Sema/SemaStmt.cpp2
-rw-r--r--lib/Sema/SemaTemplate.cpp439
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp161
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp381
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp395
-rw-r--r--lib/Sema/SemaType.cpp265
-rw-r--r--lib/Sema/TreeTransform.h896
21 files changed, 2714 insertions, 1693 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index c78ab5b3e959..9b24d55f3ece 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 fc9c14f456bd..8104dd39d052 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 6dd081bdc25e..0f84b46ed405 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 bf396041b473..8bb334855d02 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 589b0c6bd0ec..38b6ebeefab9 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 381151325a03..e9df17d6a115 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 b83181becb93..d89cb5fc97f5 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 341d49ead418..18f57da76912 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 6d1f4ea4a865..bc255137fccf 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 22a517934c7e..93f8d0dc37c1 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 ae45429952c7..ac7cced2eaef 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 d4d031f91ed5..4868c14835f4 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 dd877c16fba7..93752e130c94 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 ebcf3ad8e2bc..946e28269eb6 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 145342438503..6a65bd1dd1ec 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 0f223208a938..3c56358d5a94 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 2a44f83598e8..7b5ad7fc640e 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 53d158088c8e..dfe37d8caf17 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 be4adbc93d15..7288ae29a0e3 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 49f7119c8b06..0003b1b0c419 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 7e0972fe03c4..5713da9fa590 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);