summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-06-27 10:45:02 +0000
committered <ed@FreeBSD.org>2009-06-27 10:45:02 +0000
commitc1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a (patch)
tree2c5a83521a20c02e7805581a174008aa9bc23579 /lib/Sema
parent14660dbe9881f68a6cc2b9f014e1fb7b7228bca4 (diff)
downloadFreeBSD-src-c1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a.zip
FreeBSD-src-c1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a.tar.gz
Import Clang r74383.
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h72
-rw-r--r--lib/Sema/SemaChecking.cpp21
-rw-r--r--lib/Sema/SemaDecl.cpp97
-rw-r--r--lib/Sema/SemaDeclAttr.cpp27
-rw-r--r--lib/Sema/SemaDeclCXX.cpp195
-rw-r--r--lib/Sema/SemaExpr.cpp135
-rw-r--r--lib/Sema/SemaExprCXX.cpp4
-rw-r--r--lib/Sema/SemaInit.cpp9
-rw-r--r--lib/Sema/SemaLookup.cpp119
-rw-r--r--lib/Sema/SemaOverload.cpp106
-rw-r--r--lib/Sema/SemaTemplate.cpp61
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp424
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp176
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp74
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp10
-rw-r--r--lib/Sema/SemaType.cpp79
16 files changed, 1321 insertions, 288 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 8604fe5..2d27ccc 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -421,9 +421,12 @@ public:
virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) {
- return ActOnDeclarator(S, D, false);
+ return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false);
}
- DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition);
+
+ DeclPtrTy HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParameterLists,
+ bool IsFunctionDefinition);
void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
Scope *S);
void DiagnoseFunctionSpecifiers(Declarator& D);
@@ -437,6 +440,7 @@ public:
bool &Redeclaration);
NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, NamedDecl* PrevDecl,
+ MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition,
bool &Redeclaration);
void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
@@ -693,6 +697,11 @@ public:
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions = false,
bool ForceRValue = false);
+ void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions = false,
+ bool ForceRValue = false);
void AddConversionCandidate(CXXConversionDecl *Conversion,
Expr *From, QualType ToType,
OverloadCandidateSet& CandidateSet);
@@ -1137,7 +1146,8 @@ public:
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
- AssociatedClassSet &AssociatedClasses);
+ AssociatedClassSet &AssociatedClasses,
+ bool &GlobalScope);
bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
SourceLocation NameLoc,
@@ -1372,9 +1382,10 @@ public:
bool HasTrailingLParen,
const CXXScopeSpec &SS,
bool isAddressOfOperand);
- DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
- bool TypeDependent, bool ValueDependent,
- const CXXScopeSpec *SS = 0);
+ OwningExprResult BuildDeclRefExpr(NamedDecl *D, QualType Ty,
+ SourceLocation Loc, bool TypeDependent,
+ bool ValueDependent,
+ const CXXScopeSpec *SS = 0);
VarDecl *BuildAnonymousStructUnionMemberPath(FieldDecl *Field,
llvm::SmallVectorImpl<FieldDecl *> &Path);
OwningExprResult
@@ -1563,6 +1574,7 @@ public:
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
+ OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName);
@@ -1581,17 +1593,36 @@ public:
CXXConstructorDecl *Constructor,
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
+
+ /// MarcDestructorReferenced - Prepare for calling destructor on the
+ /// constructed decl.
+ void MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType);
/// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
+ /// DefineImplicitDestructor - Checks for feasibility of
+ /// defining this destructor as the default destructor.
+ void DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor);
+
/// DefineImplicitCopyConstructor - Checks for feasibility of
/// defining this constructor as the copy constructor.
void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor,
unsigned TypeQuals);
+
+ /// DefineImplicitOverloadedAssign - Checks for feasibility of
+ /// defining implicit this overloaded assignment operator.
+ void DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl);
+
+ /// getAssignOperatorMethod - Returns the default copy assignmment operator
+ /// for the class.
+ CXXMethodDecl *getAssignOperatorMethod(ParmVarDecl *Decl,
+ CXXRecordDecl *ClassDecl);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
@@ -2067,6 +2098,14 @@ public:
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists);
+ virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
+ virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D);
+
virtual DeclResult
ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
unsigned TagSpec,
@@ -2180,7 +2219,13 @@ public:
/// into a non-deduced context produced a type or value that
/// produces a type that does not match the original template
/// arguments provided.
- TDK_NonDeducedMismatch
+ TDK_NonDeducedMismatch,
+ /// \brief When performing template argument deduction for a function
+ /// template, there were too many call arguments.
+ TDK_TooManyArguments,
+ /// \brief When performing template argument deduction for a class
+ /// template, there were too few call arguments.
+ TDK_TooFewArguments
};
/// \brief Provides information about an attempted template argument
@@ -2260,6 +2305,12 @@ public:
const TemplateArgumentList &TemplateArgs,
TemplateDeductionInfo &Info);
+ TemplateDeductionResult
+ DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ Expr **Args, unsigned NumArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info);
+
void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
llvm::SmallVectorImpl<bool> &Deduced);
@@ -3022,6 +3073,13 @@ public:
// returns true if the cast is invalid
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+ // CheckExtVectorCast - check type constraints for extended vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size,
+ // or vectors and the element type of that vector.
+ // returns true if the cast is invalid
+ bool CheckExtVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
/// \param Method - May be null.
/// \param [out] ReturnType - The return type of the send.
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index a2ceafa..f6d6623 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -717,6 +717,8 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
if (E->isTypeDependent() || E->isValueDependent())
return false;
+ E = E->IgnoreParenCasts();
+
switch (E->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
const ConditionalOperator *C = cast<ConditionalOperator>(E);
@@ -766,6 +768,25 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall,
return false;
}
+ case Stmt::CallExprClass: {
+ const CallExpr *CE = cast<CallExpr>(E);
+ if (const ImplicitCastExpr *ICE
+ = dyn_cast<ImplicitCastExpr>(CE->getCallee())) {
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) {
+ if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+ if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>(Context)) {
+ unsigned ArgIndex = FA->getFormatIdx();
+ const Expr *Arg = CE->getArg(ArgIndex - 1);
+
+ return SemaCheckStringLiteral(Arg, TheCall, HasVAListArg,
+ format_idx, firstDataArg);
+ }
+ }
+ }
+ }
+
+ return false;
+ }
case Stmt::ObjCStringLiteralClass:
case Stmt::StringLiteralClass: {
const StringLiteral *StrE = NULL;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index eba1d58..13162d8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -319,16 +319,16 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
return;
}
}
- } else if (isa<FunctionDecl>(D) &&
- AllowOverloadingOfFunction(D, Context)) {
- // We are pushing the name of a function, which might be an
- // overloaded name.
- FunctionDecl *FD = cast<FunctionDecl>(D);
+ } else if ((isa<FunctionDecl>(D) &&
+ AllowOverloadingOfFunction(D, Context)) ||
+ isa<FunctionTemplateDecl>(D)) {
+ // We are pushing the name of a function or function template,
+ // which might be an overloaded name.
IdentifierResolver::iterator Redecl
- = std::find_if(IdResolver.begin(FD->getDeclName()),
+ = std::find_if(IdResolver.begin(D->getDeclName()),
IdResolver.end(),
std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
- FD));
+ D));
if (Redecl != IdResolver.end() &&
S->isDeclScope(DeclPtrTy::make(*Redecl))) {
// There is already a declaration of a function on our
@@ -655,7 +655,12 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) {
"Cannot merge with an overloaded function declaration");
// Verify the old decl was also a function.
- FunctionDecl *Old = dyn_cast<FunctionDecl>(OldD);
+ FunctionDecl *Old = 0;
+ if (FunctionTemplateDecl *OldFunctionTemplate
+ = dyn_cast<FunctionTemplateDecl>(OldD))
+ Old = OldFunctionTemplate->getTemplatedDecl();
+ else
+ Old = dyn_cast<FunctionDecl>(OldD);
if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -1385,7 +1390,9 @@ static bool isNearlyMatchingFunction(ASTContext &Context,
}
Sema::DeclPtrTy
-Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
+Sema::HandleDeclarator(Scope *S, Declarator &D,
+ MultiTemplateParamsArg TemplateParamLists,
+ bool IsFunctionDefinition) {
DeclarationName Name = GetNameForDeclarator(D);
// All of these full declarators require an identifier. If it doesn't have
@@ -1500,9 +1507,15 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) {
bool Redeclaration = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ if (TemplateParamLists.size()) {
+ Diag(D.getIdentifierLoc(), diag::err_template_typedef);
+ return DeclPtrTy();
+ }
+
New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
} else if (R->isFunctionType()) {
New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl,
+ move(TemplateParamLists),
IsFunctionDefinition, Redeclaration);
} else {
New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration);
@@ -1799,6 +1812,15 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
} else if (SC == VarDecl::None)
SC = VarDecl::Static;
}
+ if (SC == VarDecl::Static) {
+ if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(DC)) {
+ if (RD->isLocalClass())
+ Diag(D.getIdentifierLoc(),
+ diag::err_static_data_member_not_allowed_in_local_class)
+ << Name << RD->getDeclName();
+ }
+ }
+
// The variable can not
NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(),
@@ -1987,6 +2009,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
NamedDecl*
Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
QualType R, NamedDecl* PrevDecl,
+ MultiTemplateParamsArg TemplateParamLists,
bool IsFunctionDefinition, bool &Redeclaration) {
assert(R.getTypePtr()->isFunctionType());
@@ -2044,6 +2067,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< R->getAsFunctionType()->getResultType();
D.setInvalidType();
}
+
+ // Check that we can declare a template here.
+ if (TemplateParamLists.size() &&
+ CheckTemplateDeclScope(S, TemplateParamLists))
+ return 0;
bool isVirtualOkay = false;
FunctionDecl *NewFD;
@@ -2143,6 +2171,26 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// from the semantic context.
NewFD->setLexicalDeclContext(CurContext);
+ // If there is a template parameter list, then we are dealing with a
+ // template declaration or specialization.
+ FunctionTemplateDecl *FunctionTemplate = 0;
+ if (TemplateParamLists.size()) {
+ // FIXME: member templates!
+ TemplateParameterList *TemplateParams
+ = static_cast<TemplateParameterList *>(*TemplateParamLists.release());
+
+ if (TemplateParams->size() > 0) {
+ // This is a function template
+ FunctionTemplate = FunctionTemplateDecl::Create(Context, CurContext,
+ NewFD->getLocation(),
+ Name, TemplateParams,
+ NewFD);
+ NewFD->setDescribedFunctionTemplate(FunctionTemplate);
+ } else {
+ // FIXME: Handle function template specializations
+ }
+ }
+
// C++ [dcl.fct.spec]p5:
// The virtual specifier shall only be used in declarations of
// nonstatic class member functions that appear within a
@@ -2261,8 +2309,6 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
// Finally, we know we have the right number of parameters, install them.
NewFD->setParams(Context, Params.data(), Params.size());
-
-
// If name lookup finds a previous declaration that is not in the
// same scope as the new declaration, this may still be an
@@ -2342,6 +2388,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
&& !NewFD->isInvalidDecl())
RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
+ // Set this FunctionDecl's range up to the right paren.
+ NewFD->setLocEnd(D.getSourceRange().getEnd());
+
+ if (FunctionTemplate && NewFD->isInvalidDecl())
+ FunctionTemplate->setInvalidDecl();
+
+ if (FunctionTemplate)
+ return FunctionTemplate;
+
return NewFD;
}
@@ -2470,7 +2525,11 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
if (MergeFunctionDecl(NewFD, OldDecl))
return NewFD->setInvalidDecl();
- NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+ if (FunctionTemplateDecl *OldTemplateDecl
+ = dyn_cast<FunctionTemplateDecl>(OldDecl))
+ NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());
+ else
+ NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
}
}
@@ -2733,9 +2792,13 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
- else
+ else {
if (!RD->hasTrivialConstructor())
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
+ // FIXME. Must do all that is needed to destroy the object
+ // on scope exit. For now, just mark the destructor as used.
+ MarcDestructorReferenced(Var->getLocation(), InitType);
+ }
}
}
@@ -2987,11 +3050,15 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope,
Scope *ParentScope = FnBodyScope->getParent();
- DeclPtrTy DP = ActOnDeclarator(ParentScope, D, /*IsFunctionDefinition=*/true);
+ DeclPtrTy DP = HandleDeclarator(ParentScope, D,
+ MultiTemplateParamsArg(*this),
+ /*IsFunctionDefinition=*/true);
return ActOnStartOfFunctionDef(FnBodyScope, DP);
}
Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) {
+ if (!D)
+ return D;
FunctionDecl *FD = cast<FunctionDecl>(D.getAs<Decl>());
CurFunctionNeedsScopeChecking = false;
@@ -3219,7 +3286,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
CurContext = Context.getTranslationUnitDecl();
FunctionDecl *FD =
- dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D, DeclPtrTy()).getAs<Decl>());
+ dyn_cast<FunctionDecl>(ActOnDeclarator(TUScope, D).getAs<Decl>());
FD->setImplicit();
CurContext = PrevDC;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index d57630e..f7dd930 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -915,6 +915,30 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) {
D->addAttr(S.Context, ::new (S.Context) DLLExportAttr());
}
+static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr,
+ Sema &S) {
+ // Attribute has 3 arguments.
+ if (Attr.getNumArgs() != 3) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
+ return;
+ }
+
+ unsigned WGSize[3];
+ for (unsigned i = 0; i < 3; ++i) {
+ Expr *E = static_cast<Expr *>(Attr.getArg(i));
+ llvm::APSInt ArgNum(32);
+ if (!E->isIntegerConstantExpr(ArgNum, S.Context)) {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
+ << "reqd_work_group_size" << E->getSourceRange();
+ return;
+ }
+ WGSize[i] = (unsigned) ArgNum.getZExtValue();
+ }
+ D->addAttr(S.Context,
+ ::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1],
+ WGSize[2]));
+}
+
static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) {
// Attribute has no arguments.
if (Attr.getNumArgs() != 1) {
@@ -1736,6 +1760,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &Att
case AttributeList::AT_cf_returns_retained:
HandleNSReturnsRetainedAttr(D, Attr, S); break;
+ case AttributeList::AT_reqd_wg_size:
+ HandleReqdWorkGroupSize(D, Attr, S); break;
+
case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break;
case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break;
case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break;
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c9c6626..cf0dab5 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1625,7 +1625,8 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
Conv = Conversions->function_begin(),
ConvEnd = Conversions->function_end();
Conv != ConvEnd; ++Conv) {
- if (*Conv == Conversion->getPreviousDeclaration()) {
+ if (*Conv
+ == cast_or_null<NamedDecl>(Conversion->getPreviousDeclaration())) {
*Conv = Conversion;
return DeclPtrTy::make(Conversion);
}
@@ -1784,18 +1785,24 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S,
const CXXScopeSpec &SS,
SourceLocation IdentLoc,
IdentifierInfo *TargetName,
+ OverloadedOperatorKind Op,
AttributeList *AttrList,
bool IsTypeName) {
assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
- assert(TargetName && "Invalid TargetName.");
+ assert((TargetName || Op) && "Invalid TargetName.");
assert(IdentLoc.isValid() && "Invalid TargetName location.");
assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
UsingDecl *UsingAlias = 0;
+ DeclarationName Name;
+ if (TargetName)
+ Name = TargetName;
+ else
+ Name = Context.DeclarationNames.getCXXOperatorName(Op);
+
// Lookup target name.
- LookupResult R = LookupParsedName(S, &SS, TargetName,
- LookupOrdinaryName, false);
+ LookupResult R = LookupParsedName(S, &SS, Name, LookupOrdinaryName, false);
if (NamedDecl *NS = R) {
if (IsTypeName && !isa<TypeDecl>(NS)) {
@@ -1890,10 +1897,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (!BaseClassDecl->hasTrivialConstructor()) {
if (CXXConstructorDecl *BaseCtor =
- BaseClassDecl->getDefaultConstructor(Context)) {
- if (BaseCtor->isImplicit() && !BaseCtor->isUsed())
- MarkDeclarationReferenced(CurrentLocation, BaseCtor);
- }
+ BaseClassDecl->getDefaultConstructor(Context))
+ MarkDeclarationReferenced(CurrentLocation, BaseCtor);
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
<< Context.getTagDeclType(ClassDecl) << 1
@@ -1913,12 +1918,10 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
CXXRecordDecl *FieldClassDecl
= cast<CXXRecordDecl>(FieldClassType->getDecl());
- if (!FieldClassDecl->hasTrivialConstructor())
+ if (!FieldClassDecl->hasTrivialConstructor()) {
if (CXXConstructorDecl *FieldCtor =
- FieldClassDecl->getDefaultConstructor(Context)) {
- if (FieldCtor->isImplicit() && !FieldCtor->isUsed())
- MarkDeclarationReferenced(CurrentLocation, FieldCtor);
- }
+ FieldClassDecl->getDefaultConstructor(Context))
+ MarkDeclarationReferenced(CurrentLocation, FieldCtor);
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
<< Context.getTagDeclType(ClassDecl) << 0 <<
@@ -1928,6 +1931,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
err = true;
}
}
+ }
else if (FieldType->isReferenceType()) {
Diag(CurrentLocation, diag::err_unintialized_member)
<< Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString();
@@ -1942,7 +1946,147 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
}
if (!err)
- Constructor->setUsed();
+ Constructor->setUsed();
+ else
+ Constructor->setInvalidDecl();
+}
+
+void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
+ CXXDestructorDecl *Destructor) {
+ assert((Destructor->isImplicit() && !Destructor->isUsed()) &&
+ "DefineImplicitDestructor - call it for implicit default dtor");
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(Destructor->getDeclContext());
+ assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");
+ // C++ [class.dtor] p5
+ // Before the implicitly-declared default destructor for a class is
+ // implicitly defined, all the implicitly-declared default destructors
+ // for its base class and its non-static data members shall have been
+ // implicitly defined.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (!BaseClassDecl->hasTrivialDestructor()) {
+ if (CXXDestructorDecl *BaseDtor =
+ const_cast<CXXDestructorDecl*>(BaseClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(CurrentLocation, BaseDtor);
+ else
+ assert(false &&
+ "DefineImplicitDestructor - missing dtor in a base class");
+ }
+ }
+
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (!FieldClassDecl->hasTrivialDestructor()) {
+ if (CXXDestructorDecl *FieldDtor =
+ const_cast<CXXDestructorDecl*>(
+ FieldClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(CurrentLocation, FieldDtor);
+ else
+ assert(false &&
+ "DefineImplicitDestructor - missing dtor in class of a data member");
+ }
+ }
+ }
+ Destructor->setUsed();
+}
+
+void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation,
+ CXXMethodDecl *MethodDecl) {
+ assert((MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
+ MethodDecl->getOverloadedOperator() == OO_Equal &&
+ !MethodDecl->isUsed()) &&
+ "DefineImplicitOverloadedAssign - call it for implicit assignment op");
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(MethodDecl->getDeclContext());
+ assert(ClassDecl && "DefineImplicitOverloadedAssign - invalid constructor");
+
+ // C++[class.copy] p12
+ // Before the implicitly-declared copy assignment operator for a class is
+ // implicitly defined, all implicitly-declared copy assignment operators
+ // for its direct base classes and its nonstatic data members shall have
+ // been implicitly defined.
+ bool err = false;
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (CXXMethodDecl *BaseAssignOpMethod =
+ getAssignOperatorMethod(MethodDecl->getParamDecl(0), BaseClassDecl))
+ MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (CXXMethodDecl *FieldAssignOpMethod =
+ getAssignOperatorMethod(MethodDecl->getParamDecl(0), FieldClassDecl))
+ MarkDeclarationReferenced(CurrentLocation, FieldAssignOpMethod);
+ }
+ else if (FieldType->isReferenceType()) {
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+ << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ Diag(CurrentLocation, diag::note_first_required_here);
+ err = true;
+ }
+ else if (FieldType.isConstQualified()) {
+ Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
+ << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getNameAsCString();
+ Diag((*Field)->getLocation(), diag::note_declared_at);
+ Diag(CurrentLocation, diag::note_first_required_here);
+ err = true;
+ }
+ }
+ if (!err)
+ MethodDecl->setUsed();
+}
+
+CXXMethodDecl *
+Sema::getAssignOperatorMethod(ParmVarDecl *ParmDecl,
+ CXXRecordDecl *ClassDecl) {
+ QualType LHSType = Context.getTypeDeclType(ClassDecl);
+ QualType RHSType(LHSType);
+ // If class's assignment operator argument is const/volatile qualified,
+ // look for operator = (const/volatile B&). Otherwise, look for
+ // operator = (B&).
+ if (ParmDecl->getType().isConstQualified())
+ RHSType.addConst();
+ if (ParmDecl->getType().isVolatileQualified())
+ RHSType.addVolatile();
+ ExprOwningPtr<Expr> LHS(this, new (Context) DeclRefExpr(ParmDecl,
+ LHSType,
+ SourceLocation()));
+ ExprOwningPtr<Expr> RHS(this, new (Context) DeclRefExpr(ParmDecl,
+ RHSType,
+ SourceLocation()));
+ Expr *Args[2] = { &*LHS, &*RHS };
+ OverloadCandidateSet CandidateSet;
+ AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2,
+ CandidateSet);
+ OverloadCandidateSet::iterator Best;
+ if (BestViableFunction(CandidateSet,
+ ClassDecl->getLocation(), Best) == OR_Success)
+ return cast<CXXMethodDecl>(Best->Function);
+ assert(false &&
+ "getAssignOperatorMethod - copy assignment operator method not found");
+ return 0;
}
void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
@@ -1956,6 +2100,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+ // C++ [class.copy] p209
// Before the implicitly-declared copy constructor for a class is
// implicitly defined, all the implicitly-declared copy constructors
// for its base class and its non-static data members shall have been
@@ -1966,8 +2111,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
= cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
if (CXXConstructorDecl *BaseCopyCtor =
BaseClassDecl->getCopyConstructor(Context, TypeQuals))
- if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed())
- MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
+ MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
}
for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
Field != ClassDecl->field_end(Context);
@@ -1980,8 +2124,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
= cast<CXXRecordDecl>(FieldClassType->getDecl());
if (CXXConstructorDecl *FieldCopyCtor =
FieldClassDecl->getCopyConstructor(Context, TypeQuals))
- if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed())
- MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
+ MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
}
}
CopyConstructor->setUsed();
@@ -1997,6 +2140,16 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD,
VD->setInit(Context, Temp);
}
+void Sema::MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType)
+{
+ CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(
+ DeclInitType->getAsRecordType()->getDecl());
+ if (!ClassDecl->hasTrivialDestructor())
+ if (CXXDestructorDecl *Destructor =
+ const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context)))
+ MarkDeclarationReferenced(Loc, Destructor);
+}
+
/// AddCXXDirectInitializerToDecl - This action is called immediately after
/// ActOnDeclarator, when a C++ direct initializer is present.
/// e.g: "int x(1);"
@@ -2063,6 +2216,9 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
+ // FIXME. Must do all that is needed to destroy the object
+ // on scope exit. For now, just mark the destructor as used.
+ MarcDestructorReferenced(VDecl->getLocation(), DeclInitType);
}
return;
}
@@ -2590,7 +2746,8 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
ParamEnd = FnDecl->param_end();
Param != ParamEnd; ++Param) {
QualType ParamType = (*Param)->getType().getNonReferenceType();
- if (ParamType->isRecordType() || ParamType->isEnumeralType()) {
+ if (ParamType->isDependentType() || ParamType->isRecordType() ||
+ ParamType->isEnumeralType()) {
ClassOrEnumParam = true;
break;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 56d3bfe..383edec 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -623,17 +623,42 @@ Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
/// BuildDeclRefExpr - Build either a DeclRefExpr or a
/// QualifiedDeclRefExpr based on whether or not SS is a
/// nested-name-specifier.
-DeclRefExpr *
+Sema::OwningExprResult
Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
bool TypeDependent, bool ValueDependent,
const CXXScopeSpec *SS) {
+ if (Context.getCanonicalType(Ty) == Context.UndeducedAutoTy) {
+ Diag(Loc,
+ diag::err_auto_variable_cannot_appear_in_own_initializer)
+ << D->getDeclName();
+ return ExprError();
+ }
+
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+ if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) {
+ if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) {
+ if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) {
+ Diag(Loc, diag::err_reference_to_local_var_in_enclosing_function)
+ << D->getIdentifier() << FD->getDeclName();
+ Diag(D->getLocation(), diag::note_local_variable_declared_here)
+ << D->getIdentifier();
+ return ExprError();
+ }
+ }
+ }
+ }
+
MarkDeclarationReferenced(Loc, D);
+
+ Expr *E;
if (SS && !SS->isEmpty()) {
- return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
- ValueDependent, SS->getRange(),
+ E = new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent,
+ ValueDependent, SS->getRange(),
static_cast<NestedNameSpecifier *>(SS->getScopeRep()));
} else
- return new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
+ E = new (Context) DeclRefExpr(D, Ty, Loc, TypeDependent, ValueDependent);
+
+ return Owned(E);
}
/// getObjectForAnonymousRecordDecl - Retrieve the (unnamed) field or
@@ -968,7 +993,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// The pointer is type- and value-dependent if it points into something
// dependent.
bool Dependent = DC->isDependentContext();
- return Owned(BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS));
+ return BuildDeclRefExpr(D, DType, Loc, Dependent, Dependent, SS);
}
}
}
@@ -1061,11 +1086,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// Make the DeclRefExpr or BlockDeclRefExpr for the decl.
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D))
- return Owned(BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc,
- false, false, SS));
+ return BuildDeclRefExpr(Ovl, Context.OverloadTy, Loc,
+ false, false, SS);
else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
- return Owned(BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
- false, false, SS));
+ return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
+ false, false, SS);
ValueDecl *VD = cast<ValueDecl>(D);
// Check whether this declaration can be used. Note that we suppress
@@ -1113,7 +1138,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
QualType NoProtoType = T;
if (const FunctionProtoType *Proto = T->getAsFunctionProtoType())
NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType());
- return Owned(BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS));
+ return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS);
}
}
@@ -1194,8 +1219,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
}
}
- return Owned(BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
- TypeDependent, ValueDependent, SS));
+ return BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), Loc,
+ TypeDependent, ValueDependent, SS);
}
Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc,
@@ -1886,7 +1911,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,
// This flag determines whether or not CompName has an 's' char prefix,
// indicating that it is a string of hex values to be used as vector indices.
- bool HexSwizzle = *compStr == 's';
+ bool HexSwizzle = *compStr == 's' || *compStr == 'S';
// Check that we've found one of the special components, or that the component
// names must come from the same set.
@@ -2586,11 +2611,16 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
CommaLocs, RParenLoc));
// Determine whether this is a call to a member function.
- if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens()))
- if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) ||
- isa<CXXMethodDecl>(MemExpr->getMemberDecl()))
+ if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(Fn->IgnoreParens())) {
+ NamedDecl *MemDecl = MemExpr->getMemberDecl();
+ if (isa<OverloadedFunctionDecl>(MemDecl) ||
+ isa<CXXMethodDecl>(MemDecl) ||
+ (isa<FunctionTemplateDecl>(MemDecl) &&
+ isa<CXXMethodDecl>(
+ cast<FunctionTemplateDecl>(MemDecl)->getTemplatedDecl())))
return Owned(BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
CommaLocs, RParenLoc));
+ }
}
// If we're directly calling a function, get the appropriate declaration.
@@ -2626,13 +2656,19 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
}
OverloadedFunctionDecl *Ovl = 0;
+ FunctionTemplateDecl *FunctionTemplate = 0;
if (DRExpr) {
FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
+ if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DRExpr->getDecl())))
+ FDecl = FunctionTemplate->getTemplatedDecl();
+ else
+ FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl());
Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl());
NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl());
}
- if (Ovl || (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
+ if (Ovl || FunctionTemplate ||
+ (getLangOptions().CPlusPlus && (FDecl || UnqualifiedName))) {
// We don't perform ADL for implicit declarations of builtins.
if (FDecl && FDecl->getBuiltinID(Context) && FDecl->isImplicit())
ADL = false;
@@ -2641,7 +2677,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
if (!getLangOptions().CPlusPlus)
ADL = false;
- if (Ovl || ADL) {
+ if (Ovl || FunctionTemplate || ADL) {
FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0,
UnqualifiedName, LParenLoc, Args,
NumArgs, CommaLocs, RParenLoc, ADL);
@@ -2846,12 +2882,15 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) {
return Diag(castExpr->getLocStart(),
diag::err_typecheck_expect_scalar_operand)
<< castExpr->getType() << castExpr->getSourceRange();
- } else if (castExpr->getType()->isVectorType()) {
- if (CheckVectorCast(TyR, castExpr->getType(), castType))
+ } else if (castType->isExtVectorType()) {
+ if (CheckExtVectorCast(TyR, castType, castExpr->getType()))
return true;
} else if (castType->isVectorType()) {
if (CheckVectorCast(TyR, castType, castExpr->getType()))
return true;
+ } else if (castExpr->getType()->isVectorType()) {
+ if (CheckVectorCast(TyR, castExpr->getType(), castType))
+ return true;
} else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) {
return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
} else if (!castType->isArithmeticType()) {
@@ -2889,6 +2928,35 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {
return false;
}
+bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) {
+ assert(DestTy->isExtVectorType() && "Not an extended vector type!");
+
+ // If SrcTy is also an ExtVectorType, the types must be identical unless
+ // lax vector conversions is enabled.
+ if (SrcTy->isExtVectorType()) {
+ if (getLangOptions().LaxVectorConversions &&
+ Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy))
+ return false;
+ if (DestTy != SrcTy)
+ return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
+ return false;
+ }
+
+ // If SrcTy is a VectorType, then only the total size must match.
+ if (SrcTy->isVectorType()) {
+ if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
+ return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
+ return false;
+ }
+
+ // All scalar -> ext vector "c-style" casts are legal; the appropriate
+ // conversion will take place first from scalar to elt type, and then
+ // splat from elt type to vector.
+ return false;
+}
+
Action::OwningExprResult
Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprArg Op) {
@@ -5525,18 +5593,27 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (!Constructor->isUsed())
DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
}
- // FIXME: more checking for other implicits go here.
- else
- Constructor->setUsed(true);
- }
-
+ } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+ if (Destructor->isImplicit() && !Destructor->isUsed())
+ DefineImplicitDestructor(Loc, Destructor);
+
+ } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
+ if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() &&
+ MethodDecl->getOverloadedOperator() == OO_Equal) {
+ if (!MethodDecl->isUsed())
+ DefineImplicitOverloadedAssign(Loc, MethodDecl);
+ }
+ }
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- // Implicit instantiation of function templates
+ // Implicit instantiation of function templates and member functions of
+ // class templates.
if (!Function->getBody(Context)) {
- if (Function->getInstantiatedFromMemberFunction())
+ // FIXME: distinguish between implicit instantiations of function
+ // templates and explicit specializations (the latter don't get
+ // instantiated, naturally).
+ if (Function->getInstantiatedFromMemberFunction() ||
+ Function->getPrimaryTemplate())
PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
-
- // FIXME: check for function template specializations.
}
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index a567218..bc8fc4e 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -771,7 +771,7 @@ Sema::ActOnCXXConditionDeclarationExpr(Scope *S, SourceLocation StartLoc,
Diag(ED->getLocation(), diag::err_type_defined_in_condition);
}
- DeclPtrTy Dcl = ActOnDeclarator(S, D, DeclPtrTy());
+ DeclPtrTy Dcl = ActOnDeclarator(S, D);
if (!Dcl)
return ExprError();
AddInitializerToDecl(Dcl, move(AssignExprVal), /*DirectInit=*/false);
@@ -1567,7 +1567,7 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) {
CXXTemporary *Temp = CXXTemporary::Create(Context,
RD->getDestructor(Context));
ExprTemporaries.push_back(Temp);
-
+ MarcDestructorReferenced(E->getExprLoc(), E->getType());
// FIXME: Add the temporary to the temporaries vector.
return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E));
}
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 4508596..6b812e1 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -200,10 +200,9 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
if (InitEntity)
return Diag(InitLoc, diag::err_cannot_initialize_decl)
- << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
- << Init->getType() << Init->getSourceRange();
- else
- return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
+ << InitEntity << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
+ << Init->getType() << Init->getSourceRange();
+ return Diag(InitLoc, diag::err_cannot_initialize_decl_noname)
<< DeclType << (int)(Init->isLvalue(Context) == Expr::LV_Valid)
<< Init->getType() << Init->getSourceRange();
}
@@ -211,7 +210,7 @@ bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType,
// C99 6.7.8p16.
if (DeclType->isArrayType())
return Diag(Init->getLocStart(), diag::err_array_init_list_required)
- << Init->getSourceRange();
+ << Init->getSourceRange();
return CheckSingleInitializer(Init, DeclType, DirectInit, *this);
}
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 37e1df3..cc9e783 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -125,21 +125,32 @@ MaybeConstructOverloadSet(ASTContext &Context,
assert(!isa<OverloadedFunctionDecl>(*I) &&
"Cannot have an overloaded function");
- if (isa<FunctionDecl>(*I)) {
+ if ((*I)->isFunctionOrFunctionTemplate()) {
// If we found a function, there might be more functions. If
// so, collect them into an overload set.
DeclIterator Last = I;
OverloadedFunctionDecl *Ovl = 0;
- for (++Last; Last != IEnd && isa<FunctionDecl>(*Last); ++Last) {
+ for (++Last;
+ Last != IEnd && (*Last)->isFunctionOrFunctionTemplate();
+ ++Last) {
if (!Ovl) {
// FIXME: We leak this overload set. Eventually, we want to stop
// building the declarations for these overload sets, so there will be
// nothing to leak.
Ovl = OverloadedFunctionDecl::Create(Context, (*I)->getDeclContext(),
(*I)->getDeclName());
- Ovl->addOverload(cast<FunctionDecl>(*I));
+ NamedDecl *ND = (*I)->getUnderlyingDecl();
+ if (isa<FunctionDecl>(ND))
+ Ovl->addOverload(cast<FunctionDecl>(ND));
+ else
+ Ovl->addOverload(cast<FunctionTemplateDecl>(ND));
}
- Ovl->addOverload(cast<FunctionDecl>(*Last));
+
+ NamedDecl *ND = (*Last)->getUnderlyingDecl();
+ if (isa<FunctionDecl>(ND))
+ Ovl->addOverload(cast<FunctionDecl>(ND));
+ else
+ Ovl->addOverload(cast<FunctionTemplateDecl>(ND));
}
// If we had more than one function, we built an overload
@@ -202,11 +213,12 @@ MergeLookupResults(ASTContext &Context, LookupResultsTy &Results) {
break;
case LResult::Found: {
- NamedDecl *ND = I->getAsDecl();
+ NamedDecl *ND = I->getAsDecl()->getUnderlyingDecl();
+
if (TagDecl *TD = dyn_cast<TagDecl>(ND)) {
TagFound = Context.getCanonicalDecl(TD);
TagNames += FoundDecls.insert(TagFound)? 1 : 0;
- } else if (isa<FunctionDecl>(ND))
+ } else if (ND->isFunctionOrFunctionTemplate())
Functions += FoundDecls.insert(ND)? 1 : 0;
else
FoundDecls.insert(ND);
@@ -313,10 +325,9 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
Sema::LookupResult
Sema::LookupResult::CreateLookupResult(ASTContext &Context, NamedDecl *D) {
- if (ObjCCompatibleAliasDecl *Alias
- = dyn_cast_or_null<ObjCCompatibleAliasDecl>(D))
- D = Alias->getClassInterface();
-
+ if (D)
+ D = D->getUnderlyingDecl();
+
LookupResult Result;
Result.StoredKind = (D && isa<OverloadedFunctionDecl>(D))?
OverloadedDeclSingleDecl : SingleDecl;
@@ -334,10 +345,10 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context,
LookupResult Result;
Result.Context = &Context;
- if (F != L && isa<FunctionDecl>(*F)) {
+ if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
IdentifierResolver::iterator Next = F;
++Next;
- if (Next != L && isa<FunctionDecl>(*Next)) {
+ if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
Result.StoredKind = OverloadedDeclFromIdResolver;
Result.First = F.getAsOpaqueValue();
Result.Last = L.getAsOpaqueValue();
@@ -345,11 +356,10 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context,
}
}
- Decl *D = *F;
- if (ObjCCompatibleAliasDecl *Alias
- = dyn_cast_or_null<ObjCCompatibleAliasDecl>(D))
- D = Alias->getClassInterface();
-
+ NamedDecl *D = *F;
+ if (D)
+ D = D->getUnderlyingDecl();
+
Result.StoredKind = SingleDecl;
Result.First = reinterpret_cast<uintptr_t>(D);
Result.Last = 0;
@@ -363,10 +373,10 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context,
LookupResult Result;
Result.Context = &Context;
- if (F != L && isa<FunctionDecl>(*F)) {
+ if (F != L && (*F)->isFunctionOrFunctionTemplate()) {
DeclContext::lookup_iterator Next = F;
++Next;
- if (Next != L && isa<FunctionDecl>(*Next)) {
+ if (Next != L && (*Next)->isFunctionOrFunctionTemplate()) {
Result.StoredKind = OverloadedDeclFromDeclContext;
Result.First = reinterpret_cast<uintptr_t>(F);
Result.Last = reinterpret_cast<uintptr_t>(L);
@@ -374,10 +384,9 @@ Sema::LookupResult::CreateLookupResult(ASTContext &Context,
}
}
- Decl *D = *F;
- if (ObjCCompatibleAliasDecl *Alias
- = dyn_cast_or_null<ObjCCompatibleAliasDecl>(D))
- D = Alias->getClassInterface();
+ NamedDecl *D = *F;
+ if (D)
+ D = D->getUnderlyingDecl();
Result.StoredKind = SingleDecl;
Result.First = reinterpret_cast<uintptr_t>(D);
@@ -1083,7 +1092,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
// Lookup in a base class succeeded; return these results.
// If we found a function declaration, return an overload set.
- if (isa<FunctionDecl>(*Paths.front().Decls.first))
+ if ((*Paths.front().Decls.first)->isFunctionOrFunctionTemplate())
return LookupResult::CreateLookupResult(Context,
Paths.front().Decls.first, Paths.front().Decls.second);
@@ -1239,7 +1248,8 @@ static void
addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
ASTContext &Context,
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses) {
+ Sema::AssociatedClassSet &AssociatedClasses,
+ bool &GlobalScope) {
// C++ [basic.lookup.koenig]p2:
// [...]
// -- If T is a class type (including unions), its associated
@@ -1252,13 +1262,14 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
DeclContext *Ctx = Class->getDeclContext();
if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
AssociatedClasses.insert(EnclosingClass);
-
// Add the associated namespace for this class.
while (Ctx->isRecord())
Ctx = Ctx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
-
+ else if (Ctx->isTranslationUnit())
+ GlobalScope = true;
+
// Add the class itself. If we've already seen this class, we don't
// need to visit base classes.
if (!AssociatedClasses.insert(Class))
@@ -1288,6 +1299,8 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class,
BaseCtx = BaseCtx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(BaseCtx))
AssociatedNamespaces.insert(EnclosingNamespace);
+ else if (BaseCtx->isTranslationUnit())
+ GlobalScope = true;
// Make sure we visit the bases of this base class.
if (BaseDecl->bases_begin() != BaseDecl->bases_end())
@@ -1304,7 +1317,8 @@ static void
addAssociatedClassesAndNamespaces(QualType T,
ASTContext &Context,
Sema::AssociatedNamespaceSet &AssociatedNamespaces,
- Sema::AssociatedClassSet &AssociatedClasses) {
+ Sema::AssociatedClassSet &AssociatedClasses,
+ bool &GlobalScope) {
// C++ [basic.lookup.koenig]p2:
//
// For each argument type T in the function call, there is a set
@@ -1346,7 +1360,8 @@ addAssociatedClassesAndNamespaces(QualType T,
= dyn_cast<CXXRecordDecl>(ClassType->getDecl())) {
addAssociatedClassesAndNamespaces(ClassDecl, Context,
AssociatedNamespaces,
- AssociatedClasses);
+ AssociatedClasses,
+ GlobalScope);
return;
}
@@ -1366,6 +1381,8 @@ addAssociatedClassesAndNamespaces(QualType T,
Ctx = Ctx->getParent();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
+ else if (Ctx->isTranslationUnit())
+ GlobalScope = true;
return;
}
@@ -1377,7 +1394,8 @@ addAssociatedClassesAndNamespaces(QualType T,
// Return type
addAssociatedClassesAndNamespaces(FunctionType->getResultType(),
Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FunctionType);
if (!Proto)
@@ -1388,7 +1406,8 @@ addAssociatedClassesAndNamespaces(QualType T,
ArgEnd = Proto->arg_type_end();
Arg != ArgEnd; ++Arg)
addAssociatedClassesAndNamespaces(*Arg, Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
return;
}
@@ -1406,13 +1425,15 @@ addAssociatedClassesAndNamespaces(QualType T,
// Handle the type that the pointer to member points to.
addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(),
Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
// Handle the class type into which this points.
if (const RecordType *Class = MemberPtr->getClass()->getAsRecordType())
addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()),
Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
return;
}
@@ -1431,7 +1452,8 @@ addAssociatedClassesAndNamespaces(QualType T,
void
Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
- AssociatedClassSet &AssociatedClasses) {
+ AssociatedClassSet &AssociatedClasses,
+ bool &GlobalScope) {
AssociatedNamespaces.clear();
AssociatedClasses.clear();
@@ -1447,7 +1469,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
if (Arg->getType() != Context.OverloadTy) {
addAssociatedClassesAndNamespaces(Arg->getType(), Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
continue;
}
@@ -1475,7 +1498,9 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
FuncEnd = Ovl->function_end();
Func != FuncEnd; ++Func) {
- FunctionDecl *FDecl = cast<FunctionDecl>(*Func);
+ FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*Func);
+ if (!FDecl)
+ FDecl = cast<FunctionTemplateDecl>(*Func)->getTemplatedDecl();
// Add the namespace in which this function was defined. Note
// that, if this is a member function, we do *not* consider the
@@ -1483,11 +1508,14 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
DeclContext *Ctx = FDecl->getDeclContext();
if (NamespaceDecl *EnclosingNamespace = dyn_cast<NamespaceDecl>(Ctx))
AssociatedNamespaces.insert(EnclosingNamespace);
+ else if (Ctx->isTranslationUnit())
+ GlobalScope = true;
// Add the classes and namespaces associated with the parameter
// types and return type of this function.
addAssociatedClassesAndNamespaces(FDecl->getType(), Context,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
}
}
}
@@ -1589,8 +1617,10 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
// arguments we have.
AssociatedNamespaceSet AssociatedNamespaces;
AssociatedClassSet AssociatedClasses;
+ bool GlobalScope = false;
FindAssociatedClassesAndNamespaces(Args, NumArgs,
- AssociatedNamespaces, AssociatedClasses);
+ AssociatedNamespaces, AssociatedClasses,
+ GlobalScope);
// C++ [basic.lookup.argdep]p3:
// Let X be the lookup set produced by unqualified lookup (3.4.1)
@@ -1626,4 +1656,17 @@ void Sema::ArgumentDependentLookup(DeclarationName Name,
Functions.insert(Func);
}
}
+
+ if (GlobalScope) {
+ DeclContext::lookup_iterator I, E;
+ for (llvm::tie(I, E)
+ = Context.getTranslationUnitDecl()->lookup(Context, Name);
+ I != E; ++I) {
+ FunctionDecl *Func = dyn_cast<FunctionDecl>(*I);
+ if (!Func)
+ break;
+
+ Functions.insert(Func);
+ }
+ }
}
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 11cd510..fcc1557 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -300,7 +300,18 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
// This function overloads every function in the overload set.
return true;
- } else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
+ } else if (FunctionTemplateDecl *Old = dyn_cast<FunctionTemplateDecl>(OldD))
+ return IsOverload(New, Old->getTemplatedDecl(), MatchedDecl);
+ else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
+ FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
+
+ // C++ [temp.fct]p2:
+ // A function template can be overloaded with other function templates
+ // and with normal (non-template) functions.
+ if ((OldTemplate == 0) != (NewTemplate == 0))
+ return true;
+
// Is the function New an overload of the function Old?
QualType OldQType = Context.getCanonicalType(Old->getType());
QualType NewQType = Context.getCanonicalType(New->getType());
@@ -315,8 +326,8 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
isa<FunctionNoProtoType>(NewQType.getTypePtr()))
return false;
- FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType.getTypePtr());
- FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType.getTypePtr());
+ FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+ FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
// The signature of a function includes the types of its
// parameters (C++ 1.3.10), which includes the presence or absence
@@ -328,6 +339,22 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
NewType->arg_type_begin())))
return true;
+ // C++ [temp.over.link]p4:
+ // The signature of a function template consists of its function
+ // signature, its return type and its template parameter list. The names
+ // of the template parameters are significant only for establishing the
+ // relationship between the template parameters and the rest of the
+ // signature.
+ //
+ // We check the return type and template parameter lists for function
+ // templates first; the remaining checks follow.
+ if (NewTemplate &&
+ (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+ OldTemplate->getTemplateParameters(),
+ false, false, SourceLocation()) ||
+ OldType->getResultType() != NewType->getResultType()))
+ return true;
+
// If the function is a class member, its signature includes the
// cv-qualifiers (if any) on the function itself.
//
@@ -2048,7 +2075,9 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
assert(Proto && "Functions without a prototype cannot be overloaded");
assert(!isa<CXXConversionDecl>(Function) &&
"Use AddConversionCandidate for conversion functions");
-
+ assert(!Function->getDescribedFunctionTemplate() &&
+ "Use AddTemplateOverloadCandidate for function templates");
+
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Function)) {
if (!isa<CXXConstructorDecl>(Method)) {
// If we get here, it's because we're calling a member function
@@ -2233,6 +2262,42 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
}
}
+/// \brief Add a C++ function template as a candidate in the candidate set,
+/// using template argument deduction to produce an appropriate function
+/// template specialization.
+void
+Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ Expr **Args, unsigned NumArgs,
+ OverloadCandidateSet& CandidateSet,
+ bool SuppressUserConversions,
+ bool ForceRValue) {
+ // C++ [over.match.funcs]p7:
+ // In each case where a candidate is a function template, candidate
+ // function template specializations are generated using template argument
+ // deduction (14.8.3, 14.8.2). Those candidates are then handled as
+ // candidate functions in the usual way.113) A given name can refer to one
+ // or more function templates and also to a set of overloaded non-template
+ // functions. In such a case, the candidate functions generated from each
+ // function template are combined with the set of non-template candidate
+ // functions.
+ TemplateDeductionInfo Info(Context);
+ FunctionDecl *Specialization = 0;
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArguments(FunctionTemplate, Args, NumArgs,
+ Specialization, Info)) {
+ // FIXME: Record what happened with template argument deduction, so
+ // that we can give the user a beautiful diagnostic.
+ (void)Result;
+ return;
+ }
+
+ // Add the function template specialization produced by template argument
+ // deduction as a candidate.
+ assert(Specialization && "Missing function template specialization?");
+ AddOverloadCandidate(Specialization, Args, NumArgs, CandidateSet,
+ SuppressUserConversions, ForceRValue);
+}
+
/// AddConversionCandidate - Add a C++ conversion function as a
/// candidate in the candidate set (C++ [over.match.conv],
/// C++ [over.match.copy]). From is the expression we're converting from,
@@ -3653,8 +3718,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
} else if (IsMember)
continue;
- if (FunctionType == Context.getCanonicalType((*Fun)->getType()))
- return *Fun;
+ if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
+ if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
+ return FunDecl;
+ } else {
+ unsigned DiagID
+ = PP.getDiagnostics().getCustomDiagID(Diagnostic::Warning,
+ "Clang does not yet support templated conversion functions");
+ Diag(From->getLocStart(), DiagID);
+ }
}
return 0;
@@ -3699,10 +3771,18 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
FuncEnd = Ovl->function_end();
Func != FuncEnd; ++Func) {
- AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet);
+ DeclContext *Ctx = 0;
+ if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) {
+ AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet);
+ Ctx = FunDecl->getDeclContext();
+ } else {
+ FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func);
+ AddTemplateOverloadCandidate(FunTmpl, Args, NumArgs, CandidateSet);
+ Ctx = FunTmpl->getDeclContext();
+ }
- if ((*Func)->getDeclContext()->isRecord() ||
- (*Func)->getDeclContext()->isFunctionOrMethod())
+
+ if (Ctx->isRecord() || Ctx->isFunctionOrMethod())
ArgumentDependentLookup = false;
}
} else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) {
@@ -3711,7 +3791,13 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
if (Func->getDeclContext()->isRecord() ||
Func->getDeclContext()->isFunctionOrMethod())
ArgumentDependentLookup = false;
- }
+ } else if (FunctionTemplateDecl *FuncTemplate
+ = dyn_cast_or_null<FunctionTemplateDecl>(Callee)) {
+ AddTemplateOverloadCandidate(FuncTemplate, Args, NumArgs, CandidateSet);
+
+ if (FuncTemplate->getDeclContext()->isRecord())
+ ArgumentDependentLookup = false;
+ }
if (Callee)
UnqualifiedName = Callee->getDeclName();
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e98ebb1..cd985c5 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -67,9 +67,10 @@ TemplateNameKind Sema::isTemplateName(const IdentifierInfo &II, Scope *S,
}
}
- // FIXME: What follows is a gross hack.
+ // FIXME: What follows is a slightly less gross hack than what used to
+ // follow.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
- if (FD->getType()->isDependentType()) {
+ if (FD->getDescribedFunctionTemplate()) {
TemplateResult = TemplateTy::make(FD);
return TNK_Function_template;
}
@@ -78,7 +79,7 @@ TemplateNameKind Sema::isTemplateName(const IdentifierInfo &II, Scope *S,
for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(),
FEnd = Ovl->function_end();
F != FEnd; ++F) {
- if ((*F)->getType()->isDependentType()) {
+ if (isa<FunctionTemplateDecl>(*F)) {
TemplateResult = TemplateTy::make(Ovl);
return TNK_Function_template;
}
@@ -1808,8 +1809,8 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
!isa<TemplateTemplateParmDecl>(Template)) {
assert(isa<FunctionTemplateDecl>(Template) &&
"Only function templates are possible here");
- Diag(Arg->getSourceRange().getBegin(),
- diag::note_template_arg_refers_here_func)
+ Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template);
+ Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
<< Template;
}
@@ -1873,15 +1874,17 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
OldParmEnd = Old->end(), NewParm = New->begin();
OldParm != OldParmEnd; ++OldParm, ++NewParm) {
if ((*OldParm)->getKind() != (*NewParm)->getKind()) {
- unsigned NextDiag = diag::err_template_param_different_kind;
- if (TemplateArgLoc.isValid()) {
- Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
- NextDiag = diag::note_template_param_different_kind;
- }
- Diag((*NewParm)->getLocation(), NextDiag)
+ if (Complain) {
+ unsigned NextDiag = diag::err_template_param_different_kind;
+ if (TemplateArgLoc.isValid()) {
+ Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch);
+ NextDiag = diag::note_template_param_different_kind;
+ }
+ Diag((*NewParm)->getLocation(), NextDiag)
<< IsTemplateTemplateParm;
- Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
+ Diag((*OldParm)->getLocation(), diag::note_template_prev_declaration)
<< IsTemplateTemplateParm;
+ }
return false;
}
@@ -2499,6 +2502,40 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
return DeclPtrTy::make(Specialization);
}
+Sema::DeclPtrTy
+Sema::ActOnTemplateDeclarator(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D) {
+ return HandleDeclarator(S, D, move(TemplateParameterLists), false);
+}
+
+Sema::DeclPtrTy
+Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
+ MultiTemplateParamsArg TemplateParameterLists,
+ Declarator &D) {
+ assert(getCurFunctionDecl() == 0 && "Function parsing confused");
+ assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
+ "Not a function declarator!");
+ DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
+
+ if (FTI.hasPrototype) {
+ // FIXME: Diagnose arguments without names in C.
+ }
+
+ Scope *ParentScope = FnBodyScope->getParent();
+
+ DeclPtrTy DP = HandleDeclarator(ParentScope, D,
+ move(TemplateParameterLists),
+ /*IsFunctionDefinition=*/true);
+ FunctionTemplateDecl *FunctionTemplate
+ = cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>());
+ if (FunctionTemplate)
+ return ActOnStartOfFunctionDef(FnBodyScope,
+ DeclPtrTy::make(FunctionTemplate->getTemplatedDecl()));
+
+ return DeclPtrTy();
+}
+
// Explicit instantiation of a class template specialization
Sema::DeclResult
Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index de3e52d..3d909bb 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -18,6 +18,30 @@
#include "clang/AST/ExprCXX.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/Support/Compiler.h"
+
+namespace clang {
+ /// \brief Various flags that control template argument deduction.
+ ///
+ /// These flags can be bitwise-OR'd together.
+ enum TemplateDeductionFlags {
+ /// \brief No template argument deduction flags, which indicates the
+ /// strictest results for template argument deduction (as used for, e.g.,
+ /// matching class template partial specializations).
+ TDF_None = 0,
+ /// \brief Within template argument deduction from a function call, we are
+ /// matching with a parameter type for which the original parameter was
+ /// a reference.
+ TDF_ParamWithReferenceType = 0x1,
+ /// \brief Within template argument deduction from a function call, we
+ /// are matching in a case where we ignore cv-qualifiers.
+ TDF_IgnoreQualifiers = 0x02,
+ /// \brief Within template argument deduction from a function call,
+ /// we are matching in a case where we can perform template argument
+ /// deduction from a template-id of a derived class of the argument type.
+ TDF_DerivedClass = 0x04
+ };
+}
+
using namespace clang;
static Sema::TemplateDeductionResult
@@ -156,27 +180,52 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_Success;
}
+/// \brief Deduce the template arguments by comparing the parameter type and
+/// the argument type (C++ [temp.deduct.type]).
+///
+/// \param Context the AST context in which this deduction occurs.
+///
+/// \param TemplateParams the template parameters that we are deducing
+///
+/// \param ParamIn the parameter type
+///
+/// \param ArgIn the argument type
+///
+/// \param Info information about the template argument deduction itself
+///
+/// \param Deduced the deduced template arguments
+///
+/// \param TDF bitwise OR of the TemplateDeductionFlags bits that describe
+/// how template argument deduction is performed.
+///
+/// \returns the result of template argument deduction so far. Note that a
+/// "success" result means that template argument deduction has not yet failed,
+/// but it may still fail, later, for other reasons.
static Sema::TemplateDeductionResult
DeduceTemplateArguments(ASTContext &Context,
TemplateParameterList *TemplateParams,
QualType ParamIn, QualType ArgIn,
Sema::TemplateDeductionInfo &Info,
- llvm::SmallVectorImpl<TemplateArgument> &Deduced) {
+ llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+ unsigned TDF) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = Context.getCanonicalType(ParamIn);
QualType Arg = Context.getCanonicalType(ArgIn);
- // If the parameter type is not dependent, just compare the types
- // directly.
- if (!Param->isDependentType()) {
- if (Param == Arg)
- return Sema::TDK_Success;
-
- Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
- Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
- return Sema::TDK_NonDeducedMismatch;
+ // C++0x [temp.deduct.call]p4 bullet 1:
+ // - If the original P is a reference type, the deduced A (i.e., the type
+ // referred to by the reference) can be more cv-qualified than the
+ // transformed A.
+ if (TDF & TDF_ParamWithReferenceType) {
+ unsigned ExtraQualsOnParam
+ = Param.getCVRQualifiers() & ~Arg.getCVRQualifiers();
+ Param.setCVRQualifiers(Param.getCVRQualifiers() & ~ExtraQualsOnParam);
}
+
+ // If the parameter type is not dependent, there is nothing to deduce.
+ if (!Param->isDependentType())
+ return Sema::TDK_Success;
// C++ [temp.deduct.type]p9:
// A template type argument T, a template template argument TT or a
@@ -191,7 +240,7 @@ DeduceTemplateArguments(ASTContext &Context,
// The argument type can not be less qualified than the parameter
// type.
- if (Param.isMoreQualifiedThan(Arg)) {
+ if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
Info.FirstArg = Deduced[Index];
Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
@@ -227,8 +276,16 @@ DeduceTemplateArguments(ASTContext &Context,
Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
- if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
- return Sema::TDK_NonDeducedMismatch;
+ // Check the cv-qualifiers on the parameter and argument types.
+ if (!(TDF & TDF_IgnoreQualifiers)) {
+ if (TDF & TDF_ParamWithReferenceType) {
+ if (Param.isMoreQualifiedThan(Arg))
+ return Sema::TDK_NonDeducedMismatch;
+ } else {
+ if (Param.getCVRQualifiers() != Arg.getCVRQualifiers())
+ return Sema::TDK_NonDeducedMismatch;
+ }
+ }
switch (Param->getTypeClass()) {
// No deduction possible for these types
@@ -241,10 +298,11 @@ DeduceTemplateArguments(ASTContext &Context,
if (!PointerArg)
return Sema::TDK_NonDeducedMismatch;
+ unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass);
return DeduceTemplateArguments(Context, TemplateParams,
cast<PointerType>(Param)->getPointeeType(),
PointerArg->getPointeeType(),
- Info, Deduced);
+ Info, Deduced, SubTDF);
}
// T &
@@ -256,7 +314,7 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceTemplateArguments(Context, TemplateParams,
cast<LValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
- Info, Deduced);
+ Info, Deduced, 0);
}
// T && [C++0x]
@@ -268,7 +326,7 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceTemplateArguments(Context, TemplateParams,
cast<RValueReferenceType>(Param)->getPointeeType(),
ReferenceArg->getPointeeType(),
- Info, Deduced);
+ Info, Deduced, 0);
}
// T [] (implied, but not stated explicitly)
@@ -281,7 +339,7 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceTemplateArguments(Context, TemplateParams,
Context.getAsIncompleteArrayType(Param)->getElementType(),
IncompleteArrayArg->getElementType(),
- Info, Deduced);
+ Info, Deduced, 0);
}
// T [integer-constant]
@@ -299,7 +357,7 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceTemplateArguments(Context, TemplateParams,
ConstantArrayParm->getElementType(),
ConstantArrayArg->getElementType(),
- Info, Deduced);
+ Info, Deduced, 0);
}
// type [i]
@@ -315,7 +373,7 @@ DeduceTemplateArguments(ASTContext &Context,
= DeduceTemplateArguments(Context, TemplateParams,
DependentArrayParm->getElementType(),
ArrayArg->getElementType(),
- Info, Deduced))
+ Info, Deduced, 0))
return Result;
// Determine the array bound is something we can deduce.
@@ -371,7 +429,7 @@ DeduceTemplateArguments(ASTContext &Context,
= DeduceTemplateArguments(Context, TemplateParams,
FunctionProtoParam->getResultType(),
FunctionProtoArg->getResultType(),
- Info, Deduced))
+ Info, Deduced, 0))
return Result;
for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) {
@@ -380,14 +438,14 @@ DeduceTemplateArguments(ASTContext &Context,
= DeduceTemplateArguments(Context, TemplateParams,
FunctionProtoParam->getArgType(I),
FunctionProtoArg->getArgType(I),
- Info, Deduced))
+ Info, Deduced, 0))
return Result;
}
return Sema::TDK_Success;
}
- // template-name<T> (wheretemplate-name refers to a class template)
+ // template-name<T> (where template-name refers to a class template)
// template-name<i>
// TT<T> (TODO)
// TT<i> (TODO)
@@ -440,6 +498,11 @@ DeduceTemplateArguments(ASTContext &Context,
if (!RecordArg)
return Sema::TDK_NonDeducedMismatch;
+ // FIXME: Check TDF_DerivedClass here. When this flag is set, we need
+ // to troll through the base classes of the argument and try matching
+ // all of them. Failure to match does not mean that there is a problem,
+ // of course.
+
ClassTemplateSpecializationDecl *SpecArg
= dyn_cast<ClassTemplateSpecializationDecl>(RecordArg->getDecl());
if (!SpecArg)
@@ -489,13 +552,14 @@ DeduceTemplateArguments(ASTContext &Context,
= DeduceTemplateArguments(Context, TemplateParams,
MemPtrParam->getPointeeType(),
MemPtrArg->getPointeeType(),
- Info, Deduced))
+ Info, Deduced,
+ TDF & TDF_IgnoreQualifiers))
return Result;
return DeduceTemplateArguments(Context, TemplateParams,
QualType(MemPtrParam->getClass(), 0),
QualType(MemPtrArg->getClass(), 0),
- Info, Deduced);
+ Info, Deduced, 0);
}
// (clang extension)
@@ -513,7 +577,7 @@ DeduceTemplateArguments(ASTContext &Context,
return DeduceTemplateArguments(Context, TemplateParams,
BlockPtrParam->getPointeeType(),
BlockPtrArg->getPointeeType(), Info,
- Deduced);
+ Deduced, 0);
}
case Type::TypeOfExpr:
@@ -527,7 +591,7 @@ DeduceTemplateArguments(ASTContext &Context,
}
// FIXME: Many more cases to go (to go).
- return Sema::TDK_NonDeducedMismatch;
+ return Sema::TDK_Success;
}
static Sema::TemplateDeductionResult
@@ -544,9 +608,8 @@ DeduceTemplateArguments(ASTContext &Context,
case TemplateArgument::Type:
assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
- return DeduceTemplateArguments(Context, TemplateParams,
- Param.getAsType(),
- Arg.getAsType(), Info, Deduced);
+ return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+ Arg.getAsType(), Info, Deduced, 0);
case TemplateArgument::Declaration:
// FIXME: Implement this check
@@ -624,6 +687,62 @@ DeduceTemplateArguments(ASTContext &Context,
return Sema::TDK_Success;
}
+/// \brief Determine whether two template arguments are the same.
+static bool isSameTemplateArg(ASTContext &Context,
+ const TemplateArgument &X,
+ const TemplateArgument &Y) {
+ if (X.getKind() != Y.getKind())
+ return false;
+
+ switch (X.getKind()) {
+ case TemplateArgument::Null:
+ assert(false && "Comparing NULL template argument");
+ break;
+
+ case TemplateArgument::Type:
+ return Context.getCanonicalType(X.getAsType()) ==
+ Context.getCanonicalType(Y.getAsType());
+
+ case TemplateArgument::Declaration:
+ return Context.getCanonicalDecl(X.getAsDecl()) ==
+ Context.getCanonicalDecl(Y.getAsDecl());
+
+ case TemplateArgument::Integral:
+ return *X.getAsIntegral() == *Y.getAsIntegral();
+
+ case TemplateArgument::Expression:
+ // FIXME: We assume that all expressions are distinct, but we should
+ // really check their canonical forms.
+ return false;
+
+ case TemplateArgument::Pack:
+ if (X.pack_size() != Y.pack_size())
+ return false;
+
+ for (TemplateArgument::pack_iterator XP = X.pack_begin(),
+ XPEnd = X.pack_end(),
+ YP = Y.pack_begin();
+ XP != XPEnd; ++XP, ++YP)
+ if (!isSameTemplateArg(Context, *XP, *YP))
+ return false;
+
+ return true;
+ }
+
+ return false;
+}
+
+/// \brief Helper function to build a TemplateParameter when we don't
+/// know its type statically.
+static TemplateParameter makeTemplateParameter(Decl *D) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(D))
+ return TemplateParameter(TTP);
+ else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D))
+ return TemplateParameter(NTTP);
+
+ return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
+}
+
/// \brief Perform template argument deduction to determine whether
/// the given template arguments match the given class template
/// partial specialization per C++ [temp.class.spec.match].
@@ -688,32 +807,243 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
for (unsigned I = 0, N = PartialTemplateArgs.flat_size(); I != N; ++I) {
Decl *Param = const_cast<Decl *>(
ClassTemplate->getTemplateParameters()->getParam(I));
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
- TemplateArgument InstArg = Instantiate(PartialTemplateArgs[I],
- *DeducedArgumentList);
- if (InstArg.getKind() != TemplateArgument::Type) {
- Info.Param = TTP;
- Info.FirstArg = PartialTemplateArgs[I];
- return TDK_SubstitutionFailure;
+ TemplateArgument InstArg = Instantiate(PartialTemplateArgs[I],
+ *DeducedArgumentList);
+ if (InstArg.isNull()) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[I];
+ return TDK_SubstitutionFailure;
+ }
+
+ if (InstArg.getKind() == TemplateArgument::Expression) {
+ // When the argument is an expression, check the expression result
+ // against the actual template parameter to get down to the canonical
+ // template argument.
+ Expr *InstExpr = InstArg.getAsExpr();
+ if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+ if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[I];
+ return TDK_SubstitutionFailure;
+ }
+ } else if (TemplateTemplateParmDecl *TTP
+ = dyn_cast<TemplateTemplateParmDecl>(Param)) {
+ // FIXME: template template arguments should really resolve to decls
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
+ if (!DRE || CheckTemplateArgument(TTP, DRE)) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = PartialTemplateArgs[I];
+ return TDK_SubstitutionFailure;
+ }
}
+ }
+
+ if (!isSameTemplateArg(Context, TemplateArgs[I], InstArg)) {
+ Info.Param = makeTemplateParameter(Param);
+ Info.FirstArg = TemplateArgs[I];
+ Info.SecondArg = InstArg;
+ return TDK_NonDeducedMismatch;
+ }
+ }
- if (Context.getCanonicalType(InstArg.getAsType())
- != Context.getCanonicalType(TemplateArgs[I].getAsType())) {
- Info.Param = TTP;
- Info.FirstArg = TemplateArgs[I];
- Info.SecondArg = InstArg;
- return TDK_NonDeducedMismatch;
- }
+ if (Trap.hasErrorOccurred())
+ return TDK_SubstitutionFailure;
- continue;
- }
+ return TDK_Success;
+}
- // FIXME: Check template template arguments?
+/// \brief Determine whether the given type T is a simple-template-id type.
+static bool isSimpleTemplateIdType(QualType T) {
+ if (const TemplateSpecializationType *Spec
+ = T->getAsTemplateSpecializationType())
+ return Spec->getTemplateName().getAsTemplateDecl() != 0;
+
+ return false;
+}
+
+/// \brief Perform template argument deduction from a function call
+/// (C++ [temp.deduct.call]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param Args the function call arguments
+///
+/// \param NumArgs the number of arguments in Args
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+///
+/// FIXME: We will also need to pass in any explicitly-specified template
+/// arguments.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ Expr **Args, unsigned NumArgs,
+ FunctionDecl *&Specialization,
+ TemplateDeductionInfo &Info) {
+ FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+
+ // C++ [temp.deduct.call]p1:
+ // Template argument deduction is done by comparing each function template
+ // parameter type (call it P) with the type of the corresponding argument
+ // of the call (call it A) as described below.
+ unsigned CheckArgs = NumArgs;
+ if (NumArgs < Function->getNumParams())
+ return TDK_TooFewArguments;
+ else if (NumArgs > Function->getNumParams()) {
+ const FunctionProtoType *Proto
+ = Function->getType()->getAsFunctionProtoType();
+ if (!Proto->isVariadic())
+ return TDK_TooManyArguments;
+
+ CheckArgs = Function->getNumParams();
+ }
+
+ // Template argument deduction for function templates in a SFINAE context.
+ // Trap any errors that might occur.
+ SFINAETrap Trap(*this);
+
+ // Deduce template arguments from the function parameters.
+ llvm::SmallVector<TemplateArgument, 4> Deduced;
+ Deduced.resize(FunctionTemplate->getTemplateParameters()->size());
+ TemplateParameterList *TemplateParams
+ = FunctionTemplate->getTemplateParameters();
+ for (unsigned I = 0; I != CheckArgs; ++I) {
+ QualType ParamType = Function->getParamDecl(I)->getType();
+ QualType ArgType = Args[I]->getType();
+
+ // C++ [temp.deduct.call]p2:
+ // If P is not a reference type:
+ QualType CanonParamType = Context.getCanonicalType(ParamType);
+ bool ParamWasReference = isa<ReferenceType>(CanonParamType);
+ if (!ParamWasReference) {
+ // - If A is an array type, the pointer type produced by the
+ // array-to-pointer standard conversion (4.2) is used in place of
+ // A for type deduction; otherwise,
+ if (ArgType->isArrayType())
+ ArgType = Context.getArrayDecayedType(ArgType);
+ // - If A is a function type, the pointer type produced by the
+ // function-to-pointer standard conversion (4.3) is used in place
+ // of A for type deduction; otherwise,
+ else if (ArgType->isFunctionType())
+ ArgType = Context.getPointerType(ArgType);
+ else {
+ // - If A is a cv-qualified type, the top level cv-qualifiers of A’s
+ // type are ignored for type deduction.
+ QualType CanonArgType = Context.getCanonicalType(ArgType);
+ if (CanonArgType.getCVRQualifiers())
+ ArgType = CanonArgType.getUnqualifiedType();
+ }
+ }
+
+ // C++0x [temp.deduct.call]p3:
+ // If P is a cv-qualified type, the top level cv-qualifiers of P’s type
+ // are ignored for type deduction.
+ if (CanonParamType.getCVRQualifiers())
+ ParamType = CanonParamType.getUnqualifiedType();
+ if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) {
+ // [...] If P is a reference type, the type referred to by P is used
+ // for type deduction.
+ ParamType = ParamRefType->getPointeeType();
+
+ // [...] If P is of the form T&&, where T is a template parameter, and
+ // the argument is an lvalue, the type A& is used in place of A for
+ // type deduction.
+ if (isa<RValueReferenceType>(ParamRefType) &&
+ ParamRefType->getAsTemplateTypeParmType() &&
+ Args[I]->isLvalue(Context) == Expr::LV_Valid)
+ ArgType = Context.getLValueReferenceType(ArgType);
+ }
+
+ // C++0x [temp.deduct.call]p4:
+ // In general, the deduction process attempts to find template argument
+ // values that will make the deduced A identical to A (after the type A
+ // is transformed as described above). [...]
+ unsigned TDF = 0;
+
+ // - If the original P is a reference type, the deduced A (i.e., the
+ // type referred to by the reference) can be more cv-qualified than
+ // the transformed A.
+ if (ParamWasReference)
+ TDF |= TDF_ParamWithReferenceType;
+ // - The transformed A can be another pointer or pointer to member
+ // type that can be converted to the deduced A via a qualification
+ // conversion (4.4).
+ if (ArgType->isPointerType() || ArgType->isMemberPointerType())
+ TDF |= TDF_IgnoreQualifiers;
+ // - If P is a class and P has the form simple-template-id, then the
+ // transformed A can be a derived class of the deduced A. Likewise,
+ // if P is a pointer to a class of the form simple-template-id, the
+ // transformed A can be a pointer to a derived class pointed to by
+ // the deduced A.
+ if (isSimpleTemplateIdType(ParamType) ||
+ (isa<PointerType>(ParamType) &&
+ isSimpleTemplateIdType(
+ ParamType->getAsPointerType()->getPointeeType())))
+ TDF |= TDF_DerivedClass;
+
+ if (TemplateDeductionResult Result
+ = ::DeduceTemplateArguments(Context, TemplateParams,
+ ParamType, ArgType, Info, Deduced,
+ TDF))
+ return Result;
+
+ // FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
+ // pointer parameters.
}
- if (Trap.hasErrorOccurred())
+ InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
+ FunctionTemplate, Deduced.data(), Deduced.size());
+ if (Inst)
+ return TDK_InstantiationDepth;
+
+ // C++ [temp.deduct.type]p2:
+ // [...] or if any template argument remains neither deduced nor
+ // explicitly specified, template argument deduction fails.
+ TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
+ for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+ if (Deduced[I].isNull()) {
+ Decl *Param
+ = const_cast<Decl *>(TemplateParams->getParam(I));
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
+ Info.Param = TTP;
+ else if (NonTypeTemplateParmDecl *NTTP
+ = dyn_cast<NonTypeTemplateParmDecl>(Param))
+ Info.Param = NTTP;
+ else
+ Info.Param = cast<TemplateTemplateParmDecl>(Param);
+ return TDK_Incomplete;
+ }
+
+ Builder.Append(Deduced[I]);
+ }
+
+ // Form the template argument list from the deduced template arguments.
+ TemplateArgumentList *DeducedArgumentList
+ = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+ Info.reset(DeducedArgumentList);
+
+ // Substitute the deduced template arguments into the function template
+ // declaration to produce the function template specialization.
+ Specialization = cast_or_null<FunctionDecl>(
+ InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
+ FunctionTemplate->getDeclContext(),
+ *DeducedArgumentList));
+
+ if (!Specialization || Trap.hasErrorOccurred())
return TDK_SubstitutionFailure;
+ // Turn the specialization into an actual function template specialization.
+ Specialization->setFunctionTemplateSpecialization(Context,
+ FunctionTemplate,
+ Info.take());
return TDK_Success;
}
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 1c4e907..aed3489 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -29,10 +29,18 @@ using namespace clang;
/// instantiate the given declaration.
const TemplateArgumentList &
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
+ // Template arguments for a class template specialization.
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(D))
return Spec->getTemplateArgs();
+ // Template arguments for a function template specialization.
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
+ if (const TemplateArgumentList *TemplateArgs
+ = Function->getTemplateSpecializationArgs())
+ return *TemplateArgs;
+
+ // Template arguments for a member of a class template specialization.
DeclContext *EnclosingTemplateCtx = D->getDeclContext();
while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) {
assert(!EnclosingTemplateCtx->isFileContext() &&
@@ -158,8 +166,11 @@ void Sema::PrintInstantiationStack() {
<< Active->InstantiationRange;
} else {
FunctionDecl *Function = cast<FunctionDecl>(D);
- unsigned DiagID = diag::note_template_member_function_here;
- // FIXME: check for a function template
+ unsigned DiagID;
+ if (Function->getPrimaryTemplate())
+ DiagID = diag::note_function_template_spec_here;
+ else
+ DiagID = diag::note_template_member_function_here;
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
DiagID)
<< Function
@@ -251,88 +262,82 @@ namespace {
// Declare instantiate functions for each type.
#define TYPE(Class, Base) \
- QualType Instantiate##Class##Type(const Class##Type *T, \
- unsigned Quals) const;
+ QualType Instantiate##Class##Type(const Class##Type *T) const;
#define ABSTRACT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
};
}
QualType
-TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateExtQualType(const ExtQualType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate ExtQualType yet");
return QualType();
}
QualType
-TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateBuiltinType(const BuiltinType *T) const {
assert(false && "Builtin types are not dependent and cannot be instantiated");
- return QualType(T, Quals);
+ return QualType(T, 0);
}
QualType
TemplateTypeInstantiator::
-InstantiateFixedWidthIntType(const FixedWidthIntType *T, unsigned Quals) const {
+InstantiateFixedWidthIntType(const FixedWidthIntType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate FixedWidthIntType yet");
return QualType();
}
QualType
-TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateComplexType(const ComplexType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate ComplexType yet");
return QualType();
}
QualType
-TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiatePointerType(const PointerType *T) const {
QualType PointeeType = Instantiate(T->getPointeeType());
if (PointeeType.isNull())
return QualType();
- return SemaRef.BuildPointerType(PointeeType, Quals, Loc, Entity);
+ return SemaRef.BuildPointerType(PointeeType, 0, Loc, Entity);
}
QualType
-TemplateTypeInstantiator::InstantiateBlockPointerType(const BlockPointerType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateBlockPointerType(
+ const BlockPointerType *T) const {
QualType PointeeType = Instantiate(T->getPointeeType());
if (PointeeType.isNull())
return QualType();
- return SemaRef.BuildBlockPointerType(PointeeType, Quals, Loc, Entity);
+ return SemaRef.BuildBlockPointerType(PointeeType, 0, Loc, Entity);
}
QualType
TemplateTypeInstantiator::InstantiateLValueReferenceType(
- const LValueReferenceType *T, unsigned Quals) const {
+ const LValueReferenceType *T) const {
QualType ReferentType = Instantiate(T->getPointeeType());
if (ReferentType.isNull())
return QualType();
- return SemaRef.BuildReferenceType(ReferentType, true, Quals, Loc, Entity);
+ return SemaRef.BuildReferenceType(ReferentType, true, 0, Loc, Entity);
}
QualType
TemplateTypeInstantiator::InstantiateRValueReferenceType(
- const RValueReferenceType *T, unsigned Quals) const {
+ const RValueReferenceType *T) const {
QualType ReferentType = Instantiate(T->getPointeeType());
if (ReferentType.isNull())
return QualType();
- return SemaRef.BuildReferenceType(ReferentType, false, Quals, Loc, Entity);
+ return SemaRef.BuildReferenceType(ReferentType, false, 0, Loc, Entity);
}
QualType
TemplateTypeInstantiator::
-InstantiateMemberPointerType(const MemberPointerType *T,
- unsigned Quals) const {
+InstantiateMemberPointerType(const MemberPointerType *T) const {
QualType PointeeType = Instantiate(T->getPointeeType());
if (PointeeType.isNull())
return QualType();
@@ -341,14 +346,13 @@ InstantiateMemberPointerType(const MemberPointerType *T,
if (ClassType.isNull())
return QualType();
- return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Quals, Loc,
+ return SemaRef.BuildMemberPointerType(PointeeType, ClassType, 0, Loc,
Entity);
}
QualType
TemplateTypeInstantiator::
-InstantiateConstantArrayType(const ConstantArrayType *T,
- unsigned Quals) const {
+InstantiateConstantArrayType(const ConstantArrayType *T) const {
QualType ElementType = Instantiate(T->getElementType());
if (ElementType.isNull())
return ElementType;
@@ -383,8 +387,7 @@ InstantiateConstantArrayType(const ConstantArrayType *T,
QualType
TemplateTypeInstantiator::
-InstantiateIncompleteArrayType(const IncompleteArrayType *T,
- unsigned Quals) const {
+InstantiateIncompleteArrayType(const IncompleteArrayType *T) const {
QualType ElementType = Instantiate(T->getElementType());
if (ElementType.isNull())
return ElementType;
@@ -396,8 +399,7 @@ InstantiateIncompleteArrayType(const IncompleteArrayType *T,
QualType
TemplateTypeInstantiator::
-InstantiateVariableArrayType(const VariableArrayType *T,
- unsigned Quals) const {
+InstantiateVariableArrayType(const VariableArrayType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate VariableArrayType yet");
return QualType();
@@ -405,8 +407,7 @@ InstantiateVariableArrayType(const VariableArrayType *T,
QualType
TemplateTypeInstantiator::
-InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
- unsigned Quals) const {
+InstantiateDependentSizedArrayType(const DependentSizedArrayType *T) const {
Expr *ArraySize = T->getSizeExpr();
assert(ArraySize->isValueDependent() &&
"dependent sized array types must have value dependent size expr");
@@ -433,8 +434,8 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
QualType
TemplateTypeInstantiator::
-InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
- unsigned Quals) const {
+InstantiateDependentSizedExtVectorType(
+ const DependentSizedExtVectorType *T) const {
// Instantiate the element type if needed.
QualType ElementType = T->getElementType();
@@ -462,16 +463,15 @@ InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
}
QualType
-TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateVectorType(const VectorType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate VectorType yet");
return QualType();
}
QualType
-TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateExtVectorType(
+ const ExtVectorType *T) const {
// FIXME: Implement this
assert(false && "Cannot instantiate ExtVectorType yet");
return QualType();
@@ -479,8 +479,7 @@ TemplateTypeInstantiator::InstantiateExtVectorType(const ExtVectorType *T,
QualType
TemplateTypeInstantiator::
-InstantiateFunctionProtoType(const FunctionProtoType *T,
- unsigned Quals) const {
+InstantiateFunctionProtoType(const FunctionProtoType *T) const {
QualType ResultType = Instantiate(T->getResultType());
if (ResultType.isNull())
return ResultType;
@@ -504,15 +503,13 @@ InstantiateFunctionProtoType(const FunctionProtoType *T,
QualType
TemplateTypeInstantiator::
-InstantiateFunctionNoProtoType(const FunctionNoProtoType *T,
- unsigned Quals) const {
+InstantiateFunctionNoProtoType(const FunctionNoProtoType *T) const {
assert(false && "Functions without prototypes cannot be dependent.");
return QualType();
}
QualType
-TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T) const {
TypedefDecl *Typedef
= cast_or_null<TypedefDecl>(
SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
@@ -523,8 +520,8 @@ TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
}
QualType
-TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypeOfExprType(
+ const TypeOfExprType *T) const {
// The expression in a typeof is not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
@@ -537,8 +534,7 @@ TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
}
QualType
-TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T) const {
QualType Underlying = Instantiate(T->getUnderlyingType());
if (Underlying.isNull())
return QualType();
@@ -546,9 +542,24 @@ TemplateTypeInstantiator::InstantiateTypeOfType(const TypeOfType *T,
return SemaRef.Context.getTypeOfType(Underlying);
}
+QualType
+TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T) const {
+ // C++0x [dcl.type.simple]p4:
+ // The operand of the decltype specifier is an unevaluated operand.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Action::Unevaluated);
+
+ Sema::OwningExprResult E
+ = SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
+
+ if (E.isInvalid())
+ return QualType();
+
+ return SemaRef.Context.getDecltypeType(E.takeAs<Expr>());
+}
+
QualType
-TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T) const {
RecordDecl *Record
= cast_or_null<RecordDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
if (!Record)
@@ -558,8 +569,7 @@ TemplateTypeInstantiator::InstantiateRecordType(const RecordType *T,
}
QualType
-TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
- unsigned Quals) const {
+TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T) const {
EnumDecl *Enum
= cast_or_null<EnumDecl>(SemaRef.InstantiateCurrentDeclRef(T->getDecl()));
if (!Enum)
@@ -570,26 +580,13 @@ TemplateTypeInstantiator::InstantiateEnumType(const EnumType *T,
QualType
TemplateTypeInstantiator::
-InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
- unsigned Quals) const {
+InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const {
if (T->getDepth() == 0) {
// Replace the template type parameter with its corresponding
// template argument.
assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
"Template argument kind mismatch");
- QualType Result = TemplateArgs[T->getIndex()].getAsType();
- if (Result.isNull() || !Quals)
- return Result;
-
- // C++ [dcl.ref]p1:
- // [...] Cv-qualified references are ill-formed except when
- // the cv-qualifiers are introduced through the use of a
- // typedef (7.1.3) or of a template type argument (14.3), in
- // which case the cv-qualifiers are ignored.
- if (Quals && Result->isReferenceType())
- Quals = 0;
-
- return QualType(Result.getTypePtr(), Quals | Result.getCVRQualifiers());
+ return TemplateArgs[T->getIndex()].getAsType();
}
// The template type parameter comes from an inner template (e.g.,
@@ -599,15 +596,13 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T,
return SemaRef.Context.getTemplateTypeParmType(T->getDepth() - 1,
T->getIndex(),
T->isParameterPack(),
- T->getName())
- .getQualifiedType(Quals);
+ T->getName());
}
QualType
TemplateTypeInstantiator::
InstantiateTemplateSpecializationType(
- const TemplateSpecializationType *T,
- unsigned Quals) const {
+ const TemplateSpecializationType *T) const {
llvm::SmallVector<TemplateArgument, 4> InstantiatedTemplateArgs;
InstantiatedTemplateArgs.reserve(T->getNumArgs());
for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
@@ -633,8 +628,7 @@ InstantiateTemplateSpecializationType(
QualType
TemplateTypeInstantiator::
-InstantiateQualifiedNameType(const QualifiedNameType *T,
- unsigned Quals) const {
+InstantiateQualifiedNameType(const QualifiedNameType *T) const {
// When we instantiated a qualified name type, there's no point in
// keeping the qualification around in the instantiated result. So,
// just instantiate the named type.
@@ -643,14 +637,14 @@ InstantiateQualifiedNameType(const QualifiedNameType *T,
QualType
TemplateTypeInstantiator::
-InstantiateTypenameType(const TypenameType *T, unsigned Quals) const {
+InstantiateTypenameType(const TypenameType *T) const {
if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
// When the typename type refers to a template-id, the template-id
// is dependent and has enough information to instantiate the
// result of the typename type. Since we don't care about keeping
// the spelling of the typename type in template instantiations,
// we just instantiate the template-id.
- return InstantiateTemplateSpecializationType(TemplateId, Quals);
+ return InstantiateTemplateSpecializationType(TemplateId);
}
NestedNameSpecifier *NNS
@@ -665,24 +659,22 @@ InstantiateTypenameType(const TypenameType *T, unsigned Quals) const {
QualType
TemplateTypeInstantiator::
-InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T,
- unsigned Quals) const {
+InstantiateObjCObjectPointerType(const ObjCObjectPointerType *T) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
QualType
TemplateTypeInstantiator::
-InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCInterfaceType(const ObjCInterfaceType *T) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
QualType
TemplateTypeInstantiator::
-InstantiateObjCQualifiedInterfaceType(const ObjCQualifiedInterfaceType *T,
- unsigned Quals) const {
+InstantiateObjCQualifiedInterfaceType(
+ const ObjCQualifiedInterfaceType *T) const {
assert(false && "Objective-C types cannot be dependent");
return QualType();
}
@@ -693,17 +685,27 @@ QualType TemplateTypeInstantiator::Instantiate(QualType T) const {
if (!T->isDependentType())
return T;
+ QualType Result;
switch (T->getTypeClass()) {
#define TYPE(Class, Base) \
case Type::Class: \
- return Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr()), \
- T.getCVRQualifiers());
+ Result = Instantiate##Class##Type(cast<Class##Type>(T.getTypePtr())); \
+ break;
#define ABSTRACT_TYPE(Class, Base)
#include "clang/AST/TypeNodes.def"
}
-
- assert(false && "Not all types have been decoded for instantiation");
- return QualType();
+
+ // C++ [dcl.ref]p1:
+ // [...] Cv-qualified references are ill-formed except when
+ // the cv-qualifiers are introduced through the use of a
+ // typedef (7.1.3) or of a template type argument (14.3), in
+ // which case the cv-qualifiers are ignored.
+ //
+ // The same rule applies to function types.
+ if (!Result.isNull() && T.getCVRQualifiers() &&
+ !Result->isFunctionType() && !Result->isReferenceType())
+ Result = Result.getWithAdditionalQualifiers(T.getCVRQualifiers());
+ return Result;
}
/// \brief Instantiate the type T with a given set of template arguments.
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ece71bc..a05095f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -44,6 +44,7 @@ namespace {
Decl *VisitStaticAssertDecl(StaticAssertDecl *D);
Decl *VisitEnumDecl(EnumDecl *D);
Decl *VisitEnumConstantDecl(EnumConstantDecl *D);
+ Decl *VisitFunctionDecl(FunctionDecl *D);
Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
Decl *VisitCXXMethodDecl(CXXMethodDecl *D);
Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
@@ -61,6 +62,7 @@ namespace {
// Helper functions for instantiating methods.
QualType InstantiateFunctionType(FunctionDecl *D,
llvm::SmallVectorImpl<ParmVarDecl *> &Params);
+ bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
};
}
@@ -291,12 +293,47 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
return Record;
}
-Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
- // Only handle actual methods; we'll deal with constructors,
- // destructors, etc. separately.
- if (D->getKind() != Decl::CXXMethod)
+Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
+ // FIXME: Look for existing specializations (explicit or otherwise).
+
+ Sema::LocalInstantiationScope Scope(SemaRef);
+
+ llvm::SmallVector<ParmVarDecl *, 4> Params;
+ QualType T = InstantiateFunctionType(D, Params);
+ if (T.isNull())
return 0;
+
+ // Build the instantiated method declaration.
+ FunctionDecl *Function
+ = FunctionDecl::Create(SemaRef.Context, Owner, D->getLocation(),
+ D->getDeclName(), T, D->getStorageClass(),
+ D->isInline(), D->hasWrittenPrototype(),
+ D->getTypeSpecStartLoc());
+
+ // FIXME: friend functions
+
+ // Attach the parameters
+ for (unsigned P = 0; P < Params.size(); ++P)
+ Params[P]->setOwningFunction(Function);
+ Function->setParams(SemaRef.Context, Params.data(), Params.size());
+
+ if (InitFunctionInstantiation(Function, D))
+ Function->setInvalidDecl();
+
+ bool Redeclaration = false;
+ bool OverloadableAttrRequired = false;
+ NamedDecl *PrevDecl = 0;
+ SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
+ /*FIXME:*/OverloadableAttrRequired);
+
+
+ // FIXME: link this to the function template from which it was instantiated.
+
+ return Function;
+}
+Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
+ // FIXME: Look for existing, explicit specializations.
Sema::LocalInstantiationScope Scope(SemaRef);
llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -340,6 +377,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
+ // FIXME: Look for existing, explicit specializations.
Sema::LocalInstantiationScope Scope(SemaRef);
llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -387,6 +425,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
+ // FIXME: Look for existing, explicit specializations.
Sema::LocalInstantiationScope Scope(SemaRef);
llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -418,6 +457,7 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {
+ // FIXME: Look for existing, explicit specializations.
Sema::LocalInstantiationScope Scope(SemaRef);
llvm::SmallVector<ParmVarDecl *, 4> Params;
@@ -557,6 +597,18 @@ TemplateDeclInstantiator::InstantiateFunctionType(FunctionDecl *D,
D->getLocation(), D->getDeclName());
}
+/// \brief Initializes the common fields of an instantiation function
+/// declaration (New) from the corresponding fields of its template (Tmpl).
+///
+/// \returns true if there was an error
+bool
+TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
+ FunctionDecl *Tmpl) {
+ if (Tmpl->isDeleted())
+ New->setDeleted();
+ return false;
+}
+
/// \brief Initializes common fields of an instantiated method
/// declaration (New) from the corresponding fields of its template
/// (Tmpl).
@@ -565,6 +617,9 @@ TemplateDeclInstantiator::InstantiateFunctionType(FunctionDecl *D,
bool
TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
CXXMethodDecl *Tmpl) {
+ if (InitFunctionInstantiation(New, Tmpl))
+ return true;
+
CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner);
New->setAccess(Tmpl->getAccess());
if (Tmpl->isVirtualAsWritten()) {
@@ -573,8 +628,6 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
Record->setPOD(false);
Record->setPolymorphic(true);
}
- if (Tmpl->isDeleted())
- New->setDeleted();
if (Tmpl->isPure()) {
New->setPure();
Record->setAbstract(true);
@@ -592,16 +645,17 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
/// function.
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function) {
- // FIXME: make this work for function template specializations, too.
-
if (Function->isInvalidDecl())
return;
assert(!Function->getBody(Context) && "Already instantiated!");
// Find the function body that we'll be substituting.
- const FunctionDecl *PatternDecl
- = Function->getInstantiatedFromMemberFunction();
+ const FunctionDecl *PatternDecl = 0;
+ if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate())
+ PatternDecl = Primary->getTemplatedDecl();
+ else
+ PatternDecl = Function->getInstantiatedFromMemberFunction();
Stmt *Pattern = 0;
if (PatternDecl)
Pattern = PatternDecl->getBody(Context, PatternDecl);
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 749fb58..65a35f9 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -119,6 +119,14 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
// FIXME: Clone the expression!
return SemaRef.Owned(Arg.getAsExpr());
+ if (Arg.getKind() == TemplateArgument::Declaration) {
+ ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
+
+ // FIXME: Can VD ever have a dependent type?
+ return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
+ false, false);
+ }
+
assert(Arg.getKind() == TemplateArgument::Integral);
QualType T = Arg.getIntegralType();
if (T->isCharType() || T->isWideCharType())
@@ -400,7 +408,7 @@ TemplateExprInstantiator::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
F = Overloads->function_begin(),
FEnd = Overloads->function_end();
F != FEnd; ++F)
- Functions.insert(*F);
+ Functions.insert(cast<FunctionDecl>(*F));
// Add any functions found via argument-dependent lookup.
DeclarationName OpName
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 967f650..c6bcdc3 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -121,16 +121,18 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
if (DeclLoc.isInvalid())
DeclLoc = DS.getSourceRange().getBegin();
- if (getLangOptions().CPlusPlus && !getLangOptions().Microsoft)
+ if (getLangOptions().CPlusPlus && !getLangOptions().Microsoft) {
Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
- else
+
+ // 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;
+ } else {
Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
-
- // FIXME: If we could guarantee that the result would be well-formed, it
- // would be useful to have a code insertion hint here. However, after
- // emitting this warning/error, we often emit other errors.
+ }
}
// FALL THROUGH.
@@ -236,6 +238,19 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,
Result = Context.getTypeOfExprType(E);
break;
}
+ case DeclSpec::TST_decltype: {
+ Expr *E = static_cast<Expr *>(DS.getTypeRep());
+ assert(E && "Didn't get an expression for decltype?");
+ // TypeQuals handled by caller.
+ Result = Context.getDecltypeType(E);
+ break;
+ }
+ case DeclSpec::TST_auto: {
+ // TypeQuals handled by caller.
+ Result = Context.UndeducedAutoTy;
+ break;
+ }
+
case DeclSpec::TST_error:
Result = Context.IntTy;
isInvalid = true;
@@ -483,6 +498,12 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
return QualType();
}
+ if (Context.getCanonicalType(T) == Context.UndeducedAutoTy) {
+ Diag(Loc, diag::err_illegal_decl_array_of_auto)
+ << getPrintableNameForEntity(Entity);
+ return QualType();
+ }
+
if (const RecordType *EltTy = T->getAsRecordType()) {
// If the element type is a struct or union that contains a variadic
// array, accept it as a GNU extension: C99 6.7.2.1p2.
@@ -786,6 +807,52 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip,
break;
}
+ if (T == Context.UndeducedAutoTy) {
+ int Error = -1;
+
+ switch (D.getContext()) {
+ case Declarator::KNRTypeListContext:
+ assert(0 && "K&R type lists aren't allowed in C++");
+ break;
+ default:
+ printf("context: %d\n", D.getContext());
+ assert(0);
+ case Declarator::PrototypeContext:
+ Error = 0; // Function prototype
+ break;
+ case Declarator::MemberContext:
+ switch (cast<TagDecl>(CurContext)->getTagKind()) {
+ case TagDecl::TK_enum: assert(0 && "unhandled tag kind"); break;
+ case TagDecl::TK_struct: Error = 1; /* Struct member */ break;
+ case TagDecl::TK_union: Error = 2; /* Union member */ break;
+ case TagDecl::TK_class: Error = 3; /* Class member */ break;
+ }
+ break;
+ case Declarator::CXXCatchContext:
+ Error = 4; // Exception declaration
+ break;
+ case Declarator::TemplateParamContext:
+ Error = 5; // Template parameter
+ break;
+ case Declarator::BlockLiteralContext:
+ Error = 6; // Block literal
+ break;
+ case Declarator::FileContext:
+ case Declarator::BlockContext:
+ case Declarator::ForContext:
+ case Declarator::ConditionContext:
+ case Declarator::TypeNameContext:
+ break;
+ }
+
+ if (Error != -1) {
+ Diag(D.getDeclSpec().getTypeSpecTypeLoc(), diag::err_auto_not_allowed)
+ << Error;
+ T = Context.IntTy;
+ D.setInvalidType(true);
+ }
+ }
+
// The name we're declaring, if any.
DeclarationName Name;
if (D.getIdentifier())
OpenPOWER on IntegriCloud