From da468bf93e74598f985f4988936ee5ca2dc9a38c Mon Sep 17 00:00:00 2001 From: ed Date: Tue, 23 Jun 2009 14:50:21 +0000 Subject: Import Clang r73954. --- lib/Sema/Sema.cpp | 14 ++++- lib/Sema/Sema.h | 58 ++++++++++++++----- lib/Sema/SemaDecl.cpp | 5 +- lib/Sema/SemaDeclCXX.cpp | 98 +++++++++++++++++++++++++++----- lib/Sema/SemaExpr.cpp | 96 +++++++++++++++++++++++++++---- lib/Sema/SemaExprCXX.cpp | 25 ++++++++ lib/Sema/SemaTemplate.cpp | 92 +++++++++++++++--------------- lib/Sema/SemaTemplateDeduction.cpp | 8 +-- lib/Sema/SemaTemplateInstantiate.cpp | 11 ++++ lib/Sema/SemaTemplateInstantiateDecl.cpp | 30 +++++++++- lib/Sema/SemaTemplateInstantiateExpr.cpp | 20 ++++++- lib/Sema/SemaTemplateInstantiateStmt.cpp | 3 + 12 files changed, 363 insertions(+), 97 deletions(-) (limited to 'lib/Sema') diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index e756b41..c37f66d 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -182,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), ExternalSource(0), CurContext(0), PreDeclaratorDC(0), CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()), - GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false), + GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), CurrentInstantiationScope(0) { @@ -235,6 +235,18 @@ void Sema::DeleteStmt(StmtTy *S) { /// translation unit when EOF is reached and all but the top-level scope is /// popped. void Sema::ActOnEndOfTranslationUnit() { + // C++: Perform implicit template instantiations. + // + // FIXME: When we perform these implicit instantiations, we do not carefully + // keep track of the point of instantiation (C++ [temp.point]). This means + // that name lookup that occurs within the template instantiation will + // always happen at the end of the translation unit, so it will find + // some names that should not be found. Although this is common behavior + // for C++ compilers, it is technically wrong. In the future, we either need + // to be able to filter the results of name lookup or we need to perform + // template instantiations earlier. + PerformPendingImplicitInstantiations(); + if (!CompleteTranslationUnit) return; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 560f952..8604fe5 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -29,7 +29,9 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" +#include #include +#include #include namespace llvm { @@ -247,11 +249,18 @@ public: /// have been declared. bool GlobalNewDeleteDeclared; - /// A flag that indicates when we are processing an unevaluated operand - /// (C++0x [expr]). C99 has the same notion of declarations being - /// "used" and C++03 has the notion of "potentially evaluated", but we - /// adopt the C++0x terminology since it is most precise. - bool InUnevaluatedOperand; + /// The current expression evaluation context. + ExpressionEvaluationContext ExprEvalContext; + + typedef std::vector > + PotentiallyReferencedDecls; + + /// A stack of declarations, each element of which is a set of declarations + /// that will be marked as referenced if the corresponding potentially + /// potentially evaluated expression is potentially evaluated. Each element + /// in the stack corresponds to a PotentiallyPotentiallyEvaluated expression + /// evaluation context. + std::list PotentiallyReferencedDeclStack; /// \brief Whether the code handled by Sema should be considered a /// complete translation unit or not. @@ -1334,12 +1343,13 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs); - virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) { - bool Result = InUnevaluatedOperand; - InUnevaluatedOperand = UnevaluatedOperand; - return Result; - } - + virtual ExpressionEvaluationContext + PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext); + + virtual void + PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, + ExpressionEvaluationContext NewContext); + void MarkDeclarationReferenced(SourceLocation Loc, Decl *D); // Primary Expressions. @@ -1572,10 +1582,16 @@ public: QualType DeclInitType, Expr **Exprs, unsigned NumExprs); - /// DefineImplicitDefaultConstructor - Checks for feasibilityt of + /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); + + /// DefineImplicitCopyConstructor - Checks for feasibility of + /// defining this constructor as the copy constructor. + void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *Constructor, + unsigned TypeQuals); /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise @@ -2495,6 +2511,22 @@ public: /// variables. LocalInstantiationScope *CurrentInstantiationScope; + /// \brief An entity for which implicit template instantiation is required. + /// + /// The source location associated with the declaration is the first place in + /// the source code where the declaration was "used". It is not necessarily + /// the point of instantiation (which will be either before or after the + /// namespace-scope declaration that triggered this implicit instantiation), + /// However, it is the location that diagnostics should generally refer to, + /// because users will need to know what code triggered the instantiation. + typedef std::pair PendingImplicitInstantiation; + + /// \brief The queue of implicit template instantiations that are required + /// but have not yet been performed. + std::queue PendingImplicitInstantiations; + + void PerformPendingImplicitInstantiations(); + QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs, SourceLocation Loc, DeclarationName Entity); @@ -2550,7 +2582,7 @@ public: void InstantiateVariableDefinition(VarDecl *Var); NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D); - + // Simple function for cloning expressions. template OwningExprResult Clone(T *E) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 06fd1a1..eba1d58 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2733,12 +2733,9 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { IK_Default); if (!Constructor) Var->setInvalidDecl(); - else { + else if (!RD->hasTrivialConstructor()) InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); - // Check for valid construction. - DefineImplicitDefaultConstructor(Var->getLocation(), Constructor); - } } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 6d740eb..c9c6626 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -107,6 +107,9 @@ namespace { void Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, ExprArg defarg) { + if (!param || !defarg.get()) + return; + ParmVarDecl *Param = cast(param.getAs()); UnparsedDefaultArgLocs.erase(Param); @@ -161,6 +164,9 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, SourceLocation ArgLoc) { + if (!param) + return; + ParmVarDecl *Param = cast(param.getAs()); if (Param) Param->setUnparsedDefaultArg(); @@ -171,6 +177,9 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param, /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of /// the default argument for the parameter param failed. void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) { + if (!param) + return; + ParmVarDecl *Param = cast(param.getAs()); Param->setInvalidDecl(); @@ -415,6 +424,9 @@ Sema::BaseResult Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeTy *basetype, SourceLocation BaseLoc) { + if (!classdecl) + return true; + AdjustDeclIfTemplate(classdecl); CXXRecordDecl *Class = cast(classdecl.getAs()); QualType BaseType = QualType::getFromOpaquePtr(basetype); @@ -640,6 +652,9 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, ExprTy **Args, unsigned NumArgs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { + if (!ConstructorD) + return true; + CXXConstructorDecl *Constructor = dyn_cast(ConstructorD.getAs()); if (!Constructor) { @@ -741,8 +756,11 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits) { - CXXConstructorDecl *Constructor = - dyn_cast(ConstructorDecl.getAs()); + if (!ConstructorDecl) + return; + + CXXConstructorDecl *Constructor + = dyn_cast(ConstructorDecl.getAs()); if (!Constructor) { Diag(ColonLoc, diag::err_only_constructors_take_base_inits); @@ -957,6 +975,9 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclPtrTy TagDecl, SourceLocation LBrac, SourceLocation RBrac) { + if (!TagDecl) + return; + AdjustDeclIfTemplate(TagDecl); ActOnFields(S, RLoc, TagDecl, (DeclPtrTy*)FieldCollector->getCurFields(), @@ -1238,6 +1259,9 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) { /// name. However, it should not bring the parameters into scope; /// that will be performed by ActOnDelayedCXXMethodParameter. void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { + if (!MethodD) + return; + CXXScopeSpec SS; FunctionDecl *Method = cast(MethodD.getAs()); QualType ClassTy @@ -1253,6 +1277,9 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { /// the method declaration. For example, we could see an /// ActOnParamDefaultArgument event for this parameter. void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { + if (!ParamD) + return; + ParmVarDecl *Param = cast(ParamD.getAs()); // If this parameter has an unparsed default argument, clear it out @@ -1272,6 +1299,9 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) { /// immediately!) for this method, if it was also defined inside the /// class body. void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) { + if (!MethodD) + return; + FunctionDecl *Method = cast(MethodD.getAs()); CXXScopeSpec SS; QualType ClassTy @@ -1842,13 +1872,13 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor) { - if (!Constructor->isDefaultConstructor() || - !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined()) - return; + assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() && + !Constructor->isUsed()) && + "DefineImplicitDefaultConstructor - call it for implicit default ctor"); CXXRecordDecl *ClassDecl = cast(Constructor->getDeclContext()); - assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor"); + assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); // Before the implicitly-declared default constructor for a class is // implicitly defined, all the implicitly-declared default constructors // for its base class and its non-static data members shall have been @@ -1861,8 +1891,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, if (!BaseClassDecl->hasTrivialConstructor()) { if (CXXConstructorDecl *BaseCtor = BaseClassDecl->getDefaultConstructor(Context)) { - if (BaseCtor->isImplicit()) - BaseCtor->setImplicitMustBeDefined(); + if (BaseCtor->isImplicit() && !BaseCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, BaseCtor); } else { Diag(CurrentLocation, diag::err_defining_default_ctor) @@ -1886,8 +1916,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, if (!FieldClassDecl->hasTrivialConstructor()) if (CXXConstructorDecl *FieldCtor = FieldClassDecl->getDefaultConstructor(Context)) { - if (FieldCtor->isImplicit()) - FieldCtor->setImplicitMustBeDefined(); + if (FieldCtor->isImplicit() && !FieldCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, FieldCtor); } else { Diag(CurrentLocation, diag::err_defining_default_ctor) @@ -1912,7 +1942,49 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } } if (!err) - Constructor->setImplicitMustBeDefined(); + Constructor->setUsed(); +} + +void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, + CXXConstructorDecl *CopyConstructor, + unsigned TypeQuals) { + assert((CopyConstructor->isImplicit() && + CopyConstructor->isCopyConstructor(Context, TypeQuals) && + !CopyConstructor->isUsed()) && + "DefineImplicitCopyConstructor - call it for implicit copy ctor"); + + CXXRecordDecl *ClassDecl + = cast(CopyConstructor->getDeclContext()); + assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + // 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 + // implicitly defined. + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); + Base != ClassDecl->bases_end(); ++Base) { + CXXRecordDecl *BaseClassDecl + = cast(Base->getType()->getAsRecordType()->getDecl()); + if (CXXConstructorDecl *BaseCopyCtor = + BaseClassDecl->getCopyConstructor(Context, TypeQuals)) + if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor); + } + 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(FieldClassType->getDecl()); + if (CXXConstructorDecl *FieldCopyCtor = + FieldClassDecl->getCopyConstructor(Context, TypeQuals)) + if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed()) + MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor); + } + } + CopyConstructor->setUsed(); } void Sema::InitializeVarWithConstructor(VarDecl *VD, @@ -1921,6 +1993,7 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD, Expr **Exprs, unsigned NumExprs) { Expr *Temp = CXXConstructExpr::Create(Context, DeclInitType, Constructor, false, Exprs, NumExprs); + MarkDeclarationReferenced(VD->getLocation(), Constructor); VD->setInit(Context, Temp); } @@ -1990,9 +2063,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, VDecl->setCXXDirectInitializer(true); InitializeVarWithConstructor(VDecl, Constructor, DeclInitType, (Expr**)Exprs.release(), NumExprs); - // An implicitly-declared default constructor for a class is implicitly - // defined when it is used to creat an object of its class type. - DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor); } return; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 692502b..56d3bfe 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2134,25 +2134,32 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, MemberType = MemberType.getQualifiedType(combinedQualifiers); } + MarkDeclarationReferenced(MemberLoc, FD); return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD, MemberLoc, MemberType)); } - if (VarDecl *Var = dyn_cast(MemberDecl)) + if (VarDecl *Var = dyn_cast(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Var, MemberLoc, Var->getType().getNonReferenceType())); - if (FunctionDecl *MemberFn = dyn_cast(MemberDecl)) + } + if (FunctionDecl *MemberFn = dyn_cast(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, MemberFn, MemberLoc, MemberFn->getType())); + } if (OverloadedFunctionDecl *Ovl = dyn_cast(MemberDecl)) return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl, MemberLoc, Context.OverloadTy)); - if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) + if (EnumConstantDecl *Enum = dyn_cast(MemberDecl)) { + MarkDeclarationReferenced(MemberLoc, MemberDecl); return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Enum, MemberLoc, Enum->getType())); + } if (isa(MemberDecl)) return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type) << DeclarationName(&Member) << int(OpKind == tok::arrow)); @@ -5432,6 +5439,35 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ return false; } +Sema::ExpressionEvaluationContext +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { + // Introduce a new set of potentially referenced declarations to the stack. + if (NewContext == PotentiallyPotentiallyEvaluated) + PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls()); + + std::swap(ExprEvalContext, NewContext); + return NewContext; +} + +void +Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext, + ExpressionEvaluationContext NewContext) { + ExprEvalContext = NewContext; + + if (OldContext == PotentiallyPotentiallyEvaluated) { + // Mark any remaining declarations in the current position of the stack + // as "referenced". If they were not meant to be referenced, semantic + // analysis would have eliminated them (e.g., in ActOnCXXTypeId). + PotentiallyReferencedDecls RemainingDecls; + RemainingDecls.swap(PotentiallyReferencedDeclStack.back()); + PotentiallyReferencedDeclStack.pop_back(); + + for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(), + IEnd = RemainingDecls.end(); + I != IEnd; ++I) + MarkDeclarationReferenced(I->first, I->second); + } +} /// \brief Note that the given declaration was referenced in the source code. /// @@ -5446,6 +5482,9 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { assert(D && "No declaration?"); + if (D->isUsed()) + return; + // Mark a parameter declaration "used", regardless of whether we're in a // template or not. if (isa(D)) @@ -5456,18 +5495,55 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CurContext->isDependentContext()) return; - // If we are in an unevaluated operand, don't mark any definitions as used. - if (InUnevaluatedOperand) - return; - + switch (ExprEvalContext) { + case Unevaluated: + // We are in an expression that is not potentially evaluated; do nothing. + return; + + case PotentiallyEvaluated: + // We are in a potentially-evaluated expression, so this declaration is + // "used"; handle this below. + break; + + case PotentiallyPotentiallyEvaluated: + // We are in an expression that may be potentially evaluated; queue this + // declaration reference until we know whether the expression is + // potentially evaluated. + PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D)); + return; + } + // Note that this declaration has been used. + if (CXXConstructorDecl *Constructor = dyn_cast(D)) { + unsigned TypeQuals; + if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { + if (!Constructor->isUsed()) + DefineImplicitDefaultConstructor(Loc, Constructor); + } + else if (Constructor->isImplicit() && + Constructor->isCopyConstructor(Context, TypeQuals)) { + if (!Constructor->isUsed()) + DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); + } + // FIXME: more checking for other implicits go here. + else + Constructor->setUsed(true); + } + if (FunctionDecl *Function = dyn_cast(D)) { - // FIXME: implicit template instantiation + // Implicit instantiation of function templates + if (!Function->getBody(Context)) { + if (Function->getInstantiatedFromMemberFunction()) + PendingImplicitInstantiations.push(std::make_pair(Function, Loc)); + + // FIXME: check for function template specializations. + } + + // FIXME: keep track of references to static functions - (void)Function; Function->setUsed(true); return; - } + } if (VarDecl *Var = dyn_cast(D)) { (void)Var; diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index bec595c..a567218 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -71,6 +71,31 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl); + if (!isType) { + // C++0x [expr.typeid]p3: + // When typeid is applied to an expression other than an lvalue of a + // polymorphic class type [...] [the] expression is an unevaluated + // operand. + + // FIXME: if the type of the expression is a class type, the class + // shall be completely defined. + bool isUnevaluatedOperand = true; + Expr *E = static_cast(TyOrExpr); + if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) { + QualType T = E->getType(); + if (const RecordType *RecordT = T->getAsRecordType()) { + CXXRecordDecl *RecordD = cast(RecordT->getDecl()); + if (RecordD->isPolymorphic()) + isUnevaluatedOperand = false; + } + } + + // If this is an unevaluated operand, clear out the set of declaration + // references we have been computing. + if (isUnevaluatedOperand) + PotentiallyReferencedDeclStack.back().clear(); + } + return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr, TypeInfoType.withConst(), SourceRange(OpLoc, RParenLoc))); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index fb41b2b..e98ebb1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -847,13 +847,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. - TemplateArgumentListBuilder ConvertedTemplateArgs(Context); + TemplateArgumentListBuilder Converted(Template->getTemplateParameters(), + NumTemplateArgs); if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc, - ConvertedTemplateArgs)) + Converted)) return QualType(); - assert((ConvertedTemplateArgs.structuredSize() == + assert((Converted.structuredSize() == Template->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -871,16 +872,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // template struct A; TemplateName CanonName = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType(CanonName, - ConvertedTemplateArgs.getFlatArgumentList(), - ConvertedTemplateArgs.flatSize()); + Converted.getFlatArguments(), + Converted.flatSize()); } else if (ClassTemplateDecl *ClassTemplate = dyn_cast(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; ClassTemplateSpecializationDecl::Profile(ID, - ConvertedTemplateArgs.getFlatArgumentList(), - ConvertedTemplateArgs.flatSize()); + Converted.getFlatArguments(), + Converted.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *Decl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -892,7 +893,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, ClassTemplate->getDeclContext(), TemplateLoc, ClassTemplate, - ConvertedTemplateArgs, 0); + Converted, 0); ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); Decl->setLexicalDeclContext(CurContext); } @@ -1003,7 +1004,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, return true; // Add the converted template type argument. - Converted.push_back( + Converted.Append( TemplateArgument(Arg.getLocation(), Context.getCanonicalType(Arg.getAsType()))); return false; @@ -1061,9 +1062,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // parameter. if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { if (TTP->isParameterPack()) { - // We have an empty parameter pack. - Converted.BeginParameterPack(); - Converted.EndParameterPack(); + // We have an empty argument pack. + Converted.BeginPack(); + Converted.EndPack(); break; } @@ -1076,13 +1077,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // on the previously-computed template arguments. if (ArgType->isDependentType()) { InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArgumentList(), + Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); TemplateArgumentList TemplateArgs(Context, Converted, - /*CopyArgs=*/false, - /*FlattenArgs=*/false); + /*TakeArgs=*/false); ArgType = InstantiateType(ArgType, TemplateArgs, TTP->getDefaultArgumentLoc(), TTP->getDeclName()); @@ -1098,13 +1098,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArgumentList(), + Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); TemplateArgumentList TemplateArgs(Context, Converted, - /*CopyArgs=*/false, - /*FlattenArgs=*/false); + /*TakeArgs=*/false); Sema::OwningExprResult E = InstantiateExpr(NTTP->getDefaultArgument(), TemplateArgs); @@ -1130,14 +1129,14 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (TemplateTypeParmDecl *TTP = dyn_cast(*Param)) { if (TTP->isParameterPack()) { - Converted.BeginParameterPack(); + Converted.BeginPack(); // Check all the remaining arguments (if any). for (; ArgIdx < NumArgs; ++ArgIdx) { if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted)) Invalid = true; } - Converted.EndParameterPack(); + Converted.EndPack(); } else { if (CheckTemplateTypeArgument(TTP, Arg, Converted)) Invalid = true; @@ -1152,13 +1151,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (NTTPType->isDependentType()) { // Instantiate the type of the non-type template parameter. InstantiatingTemplate Inst(*this, TemplateLoc, - Template, Converted.getFlatArgumentList(), + Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); TemplateArgumentList TemplateArgs(Context, Converted, - /*CopyArgs=*/false, - /*FlattenArgs=*/false); + /*TakeArgs=*/false); NTTPType = InstantiateType(NTTPType, TemplateArgs, NTTP->getLocation(), NTTP->getDeclName()); @@ -1167,7 +1165,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (!NTTPType.isNull()) NTTPType = CheckNonTypeTemplateParameterType(NTTPType, NTTP->getLocation()); - if (NTTPType.isNull()) { Invalid = true; break; @@ -1185,7 +1182,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) Invalid = true; else - Converted.push_back(Result); + Converted.Append(Result); break; } @@ -1193,7 +1190,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Integral: // We've already checked this template argument, so just copy // it to the list of converted arguments. - Converted.push_back(Arg); + Converted.Append(Arg); break; case TemplateArgument::Type: @@ -1240,7 +1237,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // Add the converted template argument. Decl *D = Context.getCanonicalDecl(cast(ArgExpr)->getDecl()); - Converted.push_back(TemplateArgument(Arg.getLocation(), D)); + Converted.Append(TemplateArgument(Arg.getLocation(), D)); continue; } } @@ -1257,7 +1254,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Declaration: // We've already checked this template argument, so just copy // it to the list of converted arguments. - Converted.push_back(Arg); + Converted.Append(Arg); break; case TemplateArgument::Integral: @@ -2102,7 +2099,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // accommodate variadic templates. MirrorsPrimaryTemplate = true; - const TemplateArgument *ArgList = TemplateArgs.getFlatArgumentList(); + const TemplateArgument *ArgList = TemplateArgs.getFlatArguments(); for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { // Determine whether the template argument list of the partial @@ -2298,13 +2295,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Check that the template argument list is well-formed for this // template. - TemplateArgumentListBuilder ConvertedTemplateArgs(Context); + TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), + TemplateArgs.size()); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, ConvertedTemplateArgs)) + RAngleLoc, Converted)) return true; - assert((ConvertedTemplateArgs.structuredSize() == + assert((Converted.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -2315,8 +2313,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, bool MirrorsPrimaryTemplate; if (CheckClassTemplatePartialSpecializationArgs( ClassTemplate->getTemplateParameters(), - ConvertedTemplateArgs, - MirrorsPrimaryTemplate)) + Converted, MirrorsPrimaryTemplate)) return true; if (MirrorsPrimaryTemplate) { @@ -2338,13 +2335,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // FIXME: Template parameter list matters, too ClassTemplatePartialSpecializationDecl::Profile(ID, - ConvertedTemplateArgs.getFlatArgumentList(), - ConvertedTemplateArgs.flatSize()); + Converted.getFlatArguments(), + Converted.flatSize()); } else ClassTemplateSpecializationDecl::Profile(ID, - ConvertedTemplateArgs.getFlatArgumentList(), - ConvertedTemplateArgs.flatSize()); + Converted.getFlatArguments(), + Converted.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = 0; @@ -2387,7 +2384,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, TemplateNameLoc, TemplateParams, ClassTemplate, - ConvertedTemplateArgs, + Converted, PrevPartial); if (PrevPartial) { @@ -2437,7 +2434,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - ConvertedTemplateArgs, + Converted, PrevDecl); if (PrevDecl) { @@ -2559,13 +2556,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // Check that the template argument list is well-formed for this // template. - TemplateArgumentListBuilder ConvertedTemplateArgs(Context); + TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), + TemplateArgs.size()); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, ConvertedTemplateArgs)) + RAngleLoc, Converted)) return true; - assert((ConvertedTemplateArgs.structuredSize() == + assert((Converted.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -2573,8 +2571,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // corresponds to these arguments. llvm::FoldingSetNodeID ID; ClassTemplateSpecializationDecl::Profile(ID, - ConvertedTemplateArgs.getFlatArgumentList(), - ConvertedTemplateArgs.flatSize()); + Converted.getFlatArguments(), + Converted.flatSize()); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -2617,7 +2615,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - ConvertedTemplateArgs, 0); + Converted, 0); Specialization->setLexicalDeclContext(CurContext); CurContext->addDecl(Context, Specialization); return DeclPtrTy::make(Specialization); @@ -2643,7 +2641,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - ConvertedTemplateArgs, 0); + Converted, 0); ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 784e451..de3e52d 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -654,7 +654,8 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor // explicitly specified, template argument deduction fails. - TemplateArgumentListBuilder Builder(Context); + TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(), + Deduced.size()); for (unsigned I = 0, N = Deduced.size(); I != N; ++I) { if (Deduced[I].isNull()) { Decl *Param @@ -669,13 +670,12 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, return TDK_Incomplete; } - Builder.push_back(Deduced[I]); + Builder.Append(Deduced[I]); } // Form the template argument list from the deduced template arguments. TemplateArgumentList *DeducedArgumentList - = new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true, - /*FlattenArgs=*/true); + = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); Info.reset(DeducedArgumentList); // Substitute the deduced template arguments into the template diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3992f8c..1c4e907 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -420,6 +420,7 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T, } // Instantiate the size expression + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); Sema::OwningExprResult InstantiatedArraySize = SemaRef.InstantiateExpr(ArraySize, TemplateArgs); if (InstantiatedArraySize.isInvalid()) @@ -443,6 +444,10 @@ InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T, return QualType(); } + // The expression in a dependent-sized extended vector type is not + // potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + // Instantiate the size expression. const Expr *SizeExpr = T->getSizeExpr(); Sema::OwningExprResult InstantiatedArraySize = @@ -520,6 +525,9 @@ TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T, QualType TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T, unsigned Quals) const { + // The expression in a typeof is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + Sema::OwningExprResult E = SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs); if (E.isInvalid()) @@ -1175,6 +1183,9 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg, return Arg; case TemplateArgument::Expression: { + // Template argument expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated); + Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs); if (E.isInvalid()) return TemplateArgument(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 6d7dc2e..ece71bc 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -163,6 +163,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { if (Invalid) BitWidth = 0; else if (BitWidth) { + // The bit-width expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + OwningExprResult InstantiatedBitWidth = SemaRef.InstantiateExpr(BitWidth, TemplateArgs); if (InstantiatedBitWidth.isInvalid()) { @@ -192,6 +195,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { Expr *AssertExpr = D->getAssertExpr(); + // The expression in a static assertion is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + OwningExprResult InstantiatedAssertExpr = SemaRef.InstantiateExpr(AssertExpr, TemplateArgs); if (InstantiatedAssertExpr.isInvalid()) @@ -222,8 +228,13 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EC != ECEnd; ++EC) { // The specified value for the enumerator. OwningExprResult Value = SemaRef.Owned((Expr *)0); - if (Expr *UninstValue = EC->getInitExpr()) + if (Expr *UninstValue = EC->getInitExpr()) { + // The enumerator's value expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Action::Unevaluated); + Value = SemaRef.InstantiateExpr(UninstValue, TemplateArgs); + } // Drop the initial value and continue. bool isInvalid = false; @@ -586,6 +597,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Function->isInvalidDecl()) return; + assert(!Function->getBody(Context) && "Already instantiated!"); + // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = Function->getInstantiatedFromMemberFunction(); @@ -765,3 +778,18 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) { return D; } + +/// \brief Performs template instantiation for all implicit template +/// instantiations we have seen until this point. +void Sema::PerformPendingImplicitInstantiations() { + while (!PendingImplicitInstantiations.empty()) { + PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front(); + PendingImplicitInstantiations.pop(); + + if (FunctionDecl *Function = dyn_cast(Inst.first)) + if (!Function->getBody(Context)) + InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function); + + // FIXME: instantiation static member variables + } +} diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index bf19701..749fb58 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -714,9 +714,17 @@ TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { E->getSourceRange()); } - Sema::OwningExprResult Arg = Visit(E->getArgumentExpr()); - if (Arg.isInvalid()) - return SemaRef.ExprError(); + Sema::OwningExprResult Arg(SemaRef); + { + // C++0x [expr.sizeof]p1: + // The operand is either an expression, which is an unevaluated operand + // [...] + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + + Arg = Visit(E->getArgumentExpr()); + if (Arg.isInvalid()) + return SemaRef.ExprError(); + } Sema::OwningExprResult Result = SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(), @@ -949,6 +957,12 @@ TemplateExprInstantiator::VisitCXXTypeidExpr(CXXTypeidExpr *E) { E->getSourceRange().getEnd()); } + // We don't know whether the expression is potentially evaluated until + // after we perform semantic analysis, so the expression is potentially + // potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Action::PotentiallyPotentiallyEvaluated); + OwningExprResult Operand = Visit(E->getExprOperand()); if (Operand.isInvalid()) return SemaRef.ExprError(); diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp index efdcec8..565b95b 100644 --- a/lib/Sema/SemaTemplateInstantiateStmt.cpp +++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp @@ -145,6 +145,9 @@ TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) { } Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) { + // The case value expressions are not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); + // Instantiate left-hand case value. OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs); if (LHS.isInvalid()) -- cgit v1.1