diff options
author | ed <ed@FreeBSD.org> | 2009-06-27 10:45:02 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-06-27 10:45:02 +0000 |
commit | c1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a (patch) | |
tree | 2c5a83521a20c02e7805581a174008aa9bc23579 /lib/Sema | |
parent | 14660dbe9881f68a6cc2b9f014e1fb7b7228bca4 (diff) | |
download | FreeBSD-src-c1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a.zip FreeBSD-src-c1ff020ff2d3e7ba86f7ab986ac7569c34f2ab1a.tar.gz |
Import Clang r74383.
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 72 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 97 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 27 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 195 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 135 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 119 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 106 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 61 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 424 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 176 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 74 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateExpr.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 79 |
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()) |