diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema')
33 files changed, 5223 insertions, 2750 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/CMakeLists.txt b/contrib/llvm/tools/clang/lib/Sema/CMakeLists.txt index b54e8eb..70b4792 100644 --- a/contrib/llvm/tools/clang/lib/Sema/CMakeLists.txt +++ b/contrib/llvm/tools/clang/lib/Sema/CMakeLists.txt @@ -34,4 +34,5 @@ add_clang_library(clangSema TargetAttributesSema.cpp ) -add_dependencies(clangSema ClangDiagnosticSema ClangStmtNodes) +add_dependencies(clangSema ClangARMNeon ClangAttrClasses ClangAttrList + ClangDiagnosticSema ClangDeclNodes ClangStmtNodes) diff --git a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp index 543c1b6..3431ac6 100644 --- a/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/JumpDiagnostics.cpp @@ -65,6 +65,7 @@ class JumpScopeChecker { public: JumpScopeChecker(Stmt *Body, Sema &S); private: + void BuildScopeInformation(Decl *D, unsigned &ParentScope); void BuildScopeInformation(Stmt *S, unsigned ParentScope); void VerifyJumps(); void VerifyIndirectJumps(); @@ -130,11 +131,13 @@ static std::pair<unsigned,unsigned> InDiag = diag::note_protected_by_variable_init; CanQualType T = VD->getType()->getCanonicalTypeUnqualified(); - while (CanQual<ArrayType> AT = T->getAs<ArrayType>()) - T = AT->getElementType(); - if (CanQual<RecordType> RT = T->getAs<RecordType>()) - if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor()) - OutDiag = diag::note_exits_dtor; + if (!T->isDependentType()) { + while (CanQual<ArrayType> AT = T->getAs<ArrayType>()) + T = AT->getElementType(); + if (CanQual<RecordType> RT = T->getAs<RecordType>()) + if (!cast<CXXRecordDecl>(RT->getDecl())->hasTrivialDestructor()) + OutDiag = diag::note_exits_dtor; + } } return std::make_pair(InDiag, OutDiag); @@ -148,13 +151,33 @@ static std::pair<unsigned,unsigned> return std::make_pair(0U, 0U); } +/// \brief Build scope information for a declaration that is part of a DeclStmt. +void JumpScopeChecker::BuildScopeInformation(Decl *D, unsigned &ParentScope) { + bool isCPlusPlus = this->S.getLangOptions().CPlusPlus; + + // If this decl causes a new scope, push and switch to it. + std::pair<unsigned,unsigned> Diags + = GetDiagForGotoScopeDecl(D, isCPlusPlus); + if (Diags.first || Diags.second) { + Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, + D->getLocation())); + ParentScope = Scopes.size()-1; + } + + // If the decl has an initializer, walk it with the potentially new + // scope we just installed. + if (VarDecl *VD = dyn_cast<VarDecl>(D)) + if (Expr *Init = VD->getInit()) + BuildScopeInformation(Init, ParentScope); +} /// BuildScopeInformation - The statements from CI to CE are known to form a /// coherent VLA scope with a specified parent node. Walk through the /// statements, adding any labels or gotos to LabelAndGotoScopes and recursively /// walking the AST as needed. void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { - + bool SkipFirstSubStmt = false; + // If we found a label, remember that it is in ParentScope scope. switch (S->getStmtClass()) { case Stmt::LabelStmtClass: @@ -172,8 +195,16 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { IndirectJumps.push_back(cast<IndirectGotoStmt>(S)); break; - case Stmt::GotoStmtClass: case Stmt::SwitchStmtClass: + // Evaluate the condition variable before entering the scope of the switch + // statement. + if (VarDecl *Var = cast<SwitchStmt>(S)->getConditionVariable()) { + BuildScopeInformation(Var, ParentScope); + SkipFirstSubStmt = true; + } + // Fall through + + case Stmt::GotoStmtClass: // Remember both what scope a goto is in as well as the fact that we have // it. This makes the second scan not have to walk the AST again. LabelAndGotoScopes[S] = ParentScope; @@ -186,33 +217,22 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) { + if (SkipFirstSubStmt) { + SkipFirstSubStmt = false; + continue; + } + Stmt *SubStmt = *CI; if (SubStmt == 0) continue; - bool isCPlusPlus = this->S.getLangOptions().CPlusPlus; - // If this is a declstmt with a VLA definition, it defines a scope from here // to the end of the containing context. if (DeclStmt *DS = dyn_cast<DeclStmt>(SubStmt)) { // The decl statement creates a scope if any of the decls in it are VLAs // or have the cleanup attribute. for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); - I != E; ++I) { - // If this decl causes a new scope, push and switch to it. - std::pair<unsigned,unsigned> Diags - = GetDiagForGotoScopeDecl(*I, isCPlusPlus); - if (Diags.first || Diags.second) { - Scopes.push_back(GotoScope(ParentScope, Diags.first, Diags.second, - (*I)->getLocation())); - ParentScope = Scopes.size()-1; - } - - // If the decl has an initializer, walk it with the potentially new - // scope we just installed. - if (VarDecl *VD = dyn_cast<VarDecl>(*I)) - if (Expr *Init = VD->getInit()) - BuildScopeInformation(Init, ParentScope); - } + I != E; ++I) + BuildScopeInformation(*I, ParentScope); continue; } diff --git a/contrib/llvm/tools/clang/lib/Sema/Lookup.h b/contrib/llvm/tools/clang/lib/Sema/Lookup.h index 0961299..271bb5b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Lookup.h +++ b/contrib/llvm/tools/clang/lib/Sema/Lookup.h @@ -424,6 +424,11 @@ public: Diagnose = false; } + /// Determines whether this lookup is suppressing diagnostics. + bool isSuppressingDiagnostics() const { + return Diagnose; + } + /// Sets a 'context' source range. void setContextRange(SourceRange SR) { NameContextRange = SR; diff --git a/contrib/llvm/tools/clang/lib/Sema/Makefile b/contrib/llvm/tools/clang/lib/Sema/Makefile index 3a5a99a..90f2dff 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Makefile +++ b/contrib/llvm/tools/clang/lib/Sema/Makefile @@ -12,11 +12,9 @@ # ##===----------------------------------------------------------------------===## -LEVEL = ../../../.. +CLANG_LEVEL := ../.. LIBRARYNAME := clangSema BUILD_ARCHIVE = 1 -CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include - -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp index 523b196..cddc84e 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" @@ -43,7 +44,10 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { TUScope = S; PushDeclContext(S, Context.getTranslationUnitDecl()); - if (PP.getTargetInfo().getPointerWidth(0) >= 64) { + VAListTagName = PP.getIdentifierInfo("__va_list_tag"); + + if (!Context.isInt128Installed() && // May be set by PCHReader. + PP.getTargetInfo().getPointerWidth(0) >= 64) { TypeSourceInfo *TInfo; // Install [u]int128_t for 64-bit targets. @@ -58,6 +62,7 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { SourceLocation(), &Context.Idents.get("__uint128_t"), TInfo), TUScope); + Context.setInt128Installed(); } @@ -122,8 +127,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, IdResolver(pp.getLangOptions()), StdNamespace(0), StdBadAlloc(0), GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), - NumSFINAEErrors(0), NonInstantiationEntries(0), - CurrentInstantiationScope(0), TyposCorrected(0), + NumSFINAEErrors(0), SuppressAccessChecking(false), + NonInstantiationEntries(0), CurrentInstantiationScope(0), TyposCorrected(0), AnalysisWarnings(*this) { TUScope = 0; @@ -223,7 +228,8 @@ void Sema::ActOnEndOfTranslationUnit() { // Remove functions that turned out to be used. UnusedStaticFuncs.erase(std::remove_if(UnusedStaticFuncs.begin(), UnusedStaticFuncs.end(), - std::mem_fun(&FunctionDecl::isUsed)), + std::bind2nd(std::mem_fun(&FunctionDecl::isUsed), + true)), UnusedStaticFuncs.end()); // Check for #pragma weak identifiers that were never declared @@ -381,6 +387,34 @@ Sema::Diag(SourceLocation Loc, const PartialDiagnostic& PD) { return Builder; } +/// \brief Determines the active Scope associated with the given declaration +/// context. +/// +/// This routine maps a declaration context to the active Scope object that +/// represents that declaration context in the parser. It is typically used +/// from "scope-less" code (e.g., template instantiation, lazy creation of +/// declarations) that injects a name for name-lookup purposes and, therefore, +/// must update the Scope. +/// +/// \returns The scope corresponding to the given declaraion context, or NULL +/// if no such scope is open. +Scope *Sema::getScopeForContext(DeclContext *Ctx) { + + if (!Ctx) + return 0; + + Ctx = Ctx->getPrimaryContext(); + for (Scope *S = getCurScope(); S; S = S->getParent()) { + // Ignore scopes that cannot have declarations. This is important for + // out-of-line definitions of static class members. + if (S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) + if (DeclContext *Entity = static_cast<DeclContext *> (S->getEntity())) + if (Ctx == Entity->getPrimaryContext()) + return S; + } + + return 0; +} /// \brief Enter a new function scope void Sema::PushFunctionScope() { @@ -425,3 +459,6 @@ BlockScopeInfo *Sema::getCurBlock() { return dyn_cast<BlockScopeInfo>(FunctionScopes.back()); } + +// Pin this vtable to this file. +ExternalSemaSource::~ExternalSemaSource() {} diff --git a/contrib/llvm/tools/clang/lib/Sema/Sema.h b/contrib/llvm/tools/clang/lib/Sema/Sema.h index dfc45ac..8336918 100644 --- a/contrib/llvm/tools/clang/lib/Sema/Sema.h +++ b/contrib/llvm/tools/clang/lib/Sema/Sema.h @@ -118,7 +118,8 @@ struct FunctionScopeInfo { /// \brief Set true when a function, method contains a VLA or ObjC try block, /// which introduce scopes that need to be checked for goto conditions. If a - /// function does not contain this, then it need not have the jump checker run on it. + /// function does not contain this, then it need not have the jump checker run + /// on it. bool NeedsScopeChecking; /// \brief The number of errors that had occurred before starting this @@ -155,24 +156,25 @@ struct FunctionScopeInfo { /// \brief Retains information about a block that is currently being parsed. struct BlockScopeInfo : FunctionScopeInfo { - llvm::SmallVector<ParmVarDecl*, 8> Params; - bool hasPrototype; - bool isVariadic; bool hasBlockDeclRefExprs; BlockDecl *TheDecl; - + /// TheScope - This is the scope for the block itself, which contains /// arguments etc. Scope *TheScope; - /// ReturnType - This will get set to block result type, by looking at - /// return types, if any, in the block body. + /// ReturnType - The return type of the block, or null if the block + /// signature didn't provide an explicit return type. QualType ReturnType; + /// BlockType - The function type of the block, if one was given. + /// Its return type may be BuiltinType::Dependent. + QualType FunctionType; + BlockScopeInfo(unsigned NumErrors, Scope *BlockScope, BlockDecl *Block) - : FunctionScopeInfo(NumErrors), hasPrototype(false), isVariadic(false), - hasBlockDeclRefExprs(false), TheDecl(Block), TheScope(BlockScope) + : FunctionScopeInfo(NumErrors), hasBlockDeclRefExprs(false), + TheDecl(Block), TheScope(BlockScope) { IsBlockInfo = true; } @@ -239,6 +241,10 @@ public: /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; + /// VAListTagName - The declaration name corresponding to __va_list_tag. + /// This is used as part of a hack to omit that class from ADL results. + DeclarationName VAListTagName; + /// A RAII object to temporarily push a declaration context. class ContextRAII { private: @@ -669,6 +675,8 @@ public: virtual void ActOnEndOfTranslationUnit(); + Scope *getScopeForContext(DeclContext *Ctx); + void PushFunctionScope(); void PushBlockScope(Scope *BlockScope, BlockDecl *Block); void PopFunctionOrBlockScope(); @@ -713,9 +721,13 @@ public: // QualType adjustParameterType(QualType T); - QualType BuildPointerType(QualType T, unsigned Quals, + QualType BuildQualifiedType(QualType T, SourceLocation Loc, Qualifiers Qs); + QualType BuildQualifiedType(QualType T, SourceLocation Loc, unsigned CVR) { + return BuildQualifiedType(T, Loc, Qualifiers::fromCVRMask(CVR)); + } + QualType BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); - QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, + QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity); QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, @@ -727,13 +739,12 @@ public: bool Variadic, unsigned Quals, SourceLocation Loc, DeclarationName Entity); QualType BuildMemberPointerType(QualType T, QualType Class, - unsigned Quals, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity); - QualType BuildBlockPointerType(QualType T, unsigned Quals, + QualType BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity); - QualType GetTypeForDeclarator(Declarator &D, Scope *S, - TypeSourceInfo **TInfo = 0, - TagDecl **OwnedDecl = 0); + TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S, + TagDecl **OwnedDecl = 0); TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, TypeSourceInfo *ReturnTypeInfo); /// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo. @@ -761,8 +772,6 @@ public: const FunctionProtoType *Target, SourceLocation TargetLoc, const FunctionProtoType *Source, SourceLocation SourceLoc); - bool UnwrapSimilarPointerTypes(QualType& T1, QualType& T2); - virtual TypeResult ActOnTypeName(Scope *S, Declarator &D); bool RequireCompleteType(SourceLocation Loc, QualType T, @@ -837,6 +846,9 @@ public: bool &OverloadableAttrRequired); void CheckMain(FunctionDecl *FD); virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D); + ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, + SourceLocation Loc, + QualType T); ParmVarDecl *CheckParameter(DeclContext *DC, TypeSourceInfo *TSInfo, QualType T, IdentifierInfo *Name, @@ -1094,10 +1106,19 @@ public: /// non-function. Ovl_NonFunction }; - OverloadKind CheckOverload(FunctionDecl *New, + OverloadKind CheckOverload(Scope *S, + FunctionDecl *New, const LookupResult &OldDecls, - NamedDecl *&OldDecl); - bool IsOverload(FunctionDecl *New, FunctionDecl *Old); + NamedDecl *&OldDecl, + bool IsForUsingDecl); + bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl); + + bool TryImplicitConversion(InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *From, + bool SuppressUserConversions, + bool AllowExplicit, + bool InOverloadResolution); ImplicitConversionSequence TryImplicitConversion(Expr* From, QualType ToType, @@ -1170,6 +1191,16 @@ public: ImplicitConversionSequence TryContextuallyConvertToObjCId(Expr *From); bool PerformContextuallyConvertToObjCId(Expr *&From); + OwningExprResult + ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, + const PartialDiagnostic &NotIntDiag, + const PartialDiagnostic &IncompleteDiag, + const PartialDiagnostic &ExplicitConvDiag, + const PartialDiagnostic &ExplicitConvNote, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &AmbigNote, + const PartialDiagnostic &ConvDiag); + bool PerformObjectMemberConversion(Expr *&From, NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, @@ -1448,6 +1479,8 @@ public: void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, UnresolvedSetImpl &Functions); + DeclContext::lookup_result LookupConstructors(CXXRecordDecl *Class); + CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, @@ -1457,7 +1490,7 @@ public: VisibleDeclConsumer &Consumer); void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer); - + /// \brief The context in which typo-correction occurs. /// /// The typo-correction context affects which keywords (if any) are @@ -1508,7 +1541,7 @@ public: // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); - void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList); + void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL); void WarnUndefinedMethod(SourceLocation ImpLoc, ObjCMethodDecl *method, bool &IncompleteImpl, unsigned DiagID); @@ -1555,16 +1588,9 @@ public: /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. void CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap); + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap); - /// ProtocolConformsToSuperClass - Returns true if class has a super class - /// and it, or its nested super class conforms to the protocol. - bool ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, - const ObjCProtocolDecl *PDecl); - /// ProtocolConformsToProtocol - Returns true if 2nd Protocol (PDecl) is - /// qualified by the 1st. - bool ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, - const ObjCProtocolDecl *PDecl); /// LookupPropertyDecl - Looks up a property in the current class and all /// its protocols. @@ -1583,7 +1609,7 @@ public: const bool isReadWrite, const unsigned Attributes, bool *isOverridingProperty, - QualType T, + TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind); /// Called by ActOnProperty and HandlePropertyInClassExtension to @@ -1596,7 +1622,8 @@ public: Selector SetterSel, const bool isAssign, const bool isReadWrite, - const unsigned Attributes, QualType T, + const unsigned Attributes, + TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC = 0); @@ -1935,7 +1962,8 @@ public: OwningExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, - DeclPtrTy ObjCImpDecl); + DeclPtrTy ObjCImpDecl, + bool HasTemplateArgs); bool CheckQualifiedMemberReference(Expr *BaseExpr, QualType BaseType, const CXXScopeSpec &SS, @@ -2100,6 +2128,7 @@ public: AttributeList *AttrList); virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace); + NamespaceDecl *getStdNamespace(); virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -2196,26 +2225,69 @@ public: /// constructed variable. void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); + /// \brief Declare the implicit default constructor for the given class. + /// + /// \param ClassDecl The class declaration into which the implicit + /// default constructor will be added. + /// + /// \returns The implicitly-declared default constructor. + CXXConstructorDecl *DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl); + /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); + /// \brief Declare the implicit destructor for the given class. + /// + /// \param ClassDecl The class declaration into which the implicit + /// destructor will be added. + /// + /// \returns The implicitly-declared destructor. + CXXDestructorDecl *DeclareImplicitDestructor(CXXRecordDecl *ClassDecl); + /// DefineImplicitDestructor - Checks for feasibility of /// defining this destructor as the default destructor. void DefineImplicitDestructor(SourceLocation CurrentLocation, - CXXDestructorDecl *Destructor); + CXXDestructorDecl *Destructor); + /// \brief Declare the implicit copy constructor for the given class. + /// + /// \param S The scope of the class, which may be NULL if this is a + /// template instantiation. + /// + /// \param ClassDecl The class declaration into which the implicit + /// copy constructor will be added. + /// + /// \returns The implicitly-declared copy constructor. + CXXConstructorDecl *DeclareImplicitCopyConstructor(CXXRecordDecl *ClassDecl); + /// DefineImplicitCopyConstructor - Checks for feasibility of /// defining this constructor as the copy constructor. void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor, unsigned TypeQuals); - /// \brief Defined and implicitly-declared copy assignment operator. + /// \brief Declare the implicit copy assignment operator for the given class. + /// + /// \param S The scope of the class, which may be NULL if this is a + /// template instantiation. + /// + /// \param ClassDecl The class declaration into which the implicit + /// copy-assignment operator will be added. + /// + /// \returns The implicitly-declared copy assignment operator. + CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); + + /// \brief Defined an implicitly-declared copy assignment operator. void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MethodDecl); + /// \brief Force the declaration of any implicitly-declared members of this + /// class. + void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); + /// MaybeBindToTemporary - If the passed in expression has a record type with /// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise /// it simply returns the passed in expression. @@ -2295,7 +2367,7 @@ public: SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - bool ParenTypeId, Declarator &D, + SourceRange TypeIdParens, Declarator &D, SourceLocation ConstructorLParen, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen); @@ -2303,7 +2375,7 @@ public: SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - bool ParenTypeId, + SourceRange TypeIdParens, QualType AllocType, SourceLocation TypeLoc, SourceRange TypeRange, @@ -2529,6 +2601,10 @@ public: virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS); + virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, + SourceLocation ColonLoc); + virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, @@ -2605,14 +2681,14 @@ public: /// \returns true if any work was done, false otherwise. bool DefineUsedVTables(); - void AddImplicitlyDeclaredMembersToClass(Scope *S, CXXRecordDecl *ClassDecl); + void AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl); virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, MemInitTy **MemInits, unsigned NumMemInits, bool AnyErrors); - void CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record); + void CheckCompletedCXXClass(CXXRecordDecl *Record); virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclPtrTy TagDecl, SourceLocation LBrac, @@ -2644,7 +2720,7 @@ public: QualType CheckConstructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC); void CheckConstructor(CXXConstructorDecl *Constructor); - QualType CheckDestructorDeclarator(Declarator &D, + QualType CheckDestructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC); bool CheckDestructor(CXXDestructorDecl *Destructor); void CheckConversionDeclarator(Declarator &D, QualType &R, @@ -2718,6 +2794,7 @@ public: const CXXMethodDecl *Old); bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange); + //===--------------------------------------------------------------------===// // C++ Access Control // @@ -2744,7 +2821,8 @@ public: AccessResult CheckConstructorAccess(SourceLocation Loc, CXXConstructorDecl *D, const InitializedEntity &Entity, - AccessSpecifier Access); + AccessSpecifier Access, + bool IsCopyBindingRefToTemp = false); AccessResult CheckDestructorAccess(SourceLocation Loc, CXXDestructorDecl *Dtor, const PartialDiagnostic &PDiag); @@ -2772,6 +2850,12 @@ public: void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx); + /// A flag to suppress access checking. + bool SuppressAccessChecking; + + void ActOnStartSuppressingAccessChecks(); + void ActOnStopSuppressingAccessChecks(); + enum AbstractDiagSelID { AbstractNone = -1, AbstractReturnType, @@ -2826,29 +2910,25 @@ public: SourceLocation KeyLoc, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position); - virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam, - SourceLocation EqualLoc, - SourceLocation DefaultLoc, - TypeTy *Default); + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + TypeTy *DefaultArg); QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc); virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Depth, - unsigned Position); - virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam, - SourceLocation EqualLoc, - ExprArg Default); + unsigned Position, + SourceLocation EqualLoc, + ExprArg DefaultArg); virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, SourceLocation TmpLoc, TemplateParamsTy *Params, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, unsigned Depth, - unsigned Position); - virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, - SourceLocation EqualLoc, - const ParsedTemplateArgument &Default); + unsigned Position, + SourceLocation EqualLoc, + const ParsedTemplateArgument &DefaultArg); virtual TemplateParamsTy * ActOnTemplateParameterList(unsigned Depth, @@ -2876,7 +2956,8 @@ public: TemplateParameterList **ParamLists, unsigned NumParamLists, bool IsFriend, - bool &IsExplicitSpecialization); + bool &IsExplicitSpecialization, + bool &Invalid); DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, @@ -2912,11 +2993,13 @@ public: SourceLocation NameLoc, const TemplateArgumentListInfo &TemplateArgs); - virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext); + virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Template); bool CheckClassTemplatePartialSpecializationArgs( TemplateParameterList *TemplateParams, @@ -2940,7 +3023,7 @@ public: Declarator &D); virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, - MultiTemplateParamsArg TemplateParameterLists, + MultiTemplateParamsArg TemplateParameterLists, Declarator &D); bool @@ -2948,7 +3031,7 @@ public: TemplateSpecializationKind NewTSK, NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK, - SourceLocation PrevPointOfInstantiation, + SourceLocation PrevPtOfInstantiation, bool &SuppressNew); bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, @@ -3096,25 +3179,29 @@ public: /// \brief Called when the parser has parsed a C++ typename /// specifier, e.g., "typename T::type". /// + /// \param S The scope in which this typename type occurs. /// \param TypenameLoc the location of the 'typename' keyword /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param II the identifier we're retrieving (e.g., 'type' in the example). /// \param IdLoc the location of the identifier. virtual TypeResult - ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - const IdentifierInfo &II, SourceLocation IdLoc); + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, + SourceLocation IdLoc); /// \brief Called when the parser has parsed a C++ typename /// specifier that ends in a template-id, e.g., /// "typename MetaFun::template apply<T1, T2>". /// + /// \param S The scope in which this typename type occurs. /// \param TypenameLoc the location of the 'typename' keyword /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param TemplateLoc the location of the 'template' keyword, if any. /// \param Ty the type that the typename specifier refers to. virtual TypeResult - ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - SourceLocation TemplateLoc, TypeTy *Ty); + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, SourceLocation TemplateLoc, + TypeTy *Ty); QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, @@ -3478,6 +3565,12 @@ public: /// to implement it anywhere else. ActiveTemplateInstantiation LastTemplateInstantiationErrorContext; + /// \brief The stack of calls expression undergoing template instantiation. + /// + /// The top of this stack is used by a fixit instantiating unresolved + /// function calls to fix the AST to match the textual change it prints. + llvm::SmallVector<CallExpr *, 8> CallsUndergoingInstantiation; + /// \brief A stack object to be created when performing template /// instantiation. /// @@ -3878,7 +3971,7 @@ public: SourceLocation *IdentLocs, unsigned NumElts); - virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, + virtual DeclPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, const IdentifierLocPair *IdentList, unsigned NumElts, AttributeList *attrList); @@ -4057,6 +4150,9 @@ public: /// FreePackedContext - Deallocate and null out PackContext. void FreePackedContext(); + /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. + void AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E); + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. @@ -4232,7 +4328,7 @@ public: bool IgnoreBaseAccess = false); bool PerformImplicitConversion(Expr *&From, QualType ToType, const StandardConversionSequence& SCS, - AssignmentAction Action, bool IgnoreBaseAccess); + AssignmentAction Action,bool IgnoreBaseAccess); /// the following "Check" methods will return a valid/converted QualType /// or a null QualType (indicating an error diagnostic was issued). @@ -4253,11 +4349,12 @@ public: QualType CheckShiftOperands( // C99 6.5.7 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, bool isRelational); + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + bool isRelational); QualType CheckBitwiseOperands( // C99 6.5.[10...12] Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation OpLoc); + Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc); // CheckAssignmentOperands is used for both simple and compound assignment. // For simple assignment, pass both expressions and a null converted type. // For compound assignment, pass both expressions and the converted type. @@ -4413,6 +4510,7 @@ public: //@{ virtual void CodeCompleteOrdinaryName(Scope *S, CodeCompletionContext CompletionContext); + virtual void CodeCompleteExpression(Scope *S, QualType T); virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base, SourceLocation OpLoc, bool IsArrow); @@ -4420,6 +4518,10 @@ public: virtual void CodeCompleteCase(Scope *S); virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, ExprTy **Args, unsigned NumArgs); + virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D); + virtual void CodeCompleteReturn(Scope *S); + virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS); + virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext); virtual void CodeCompleteUsing(Scope *S); @@ -4440,7 +4542,7 @@ public: virtual void CodeCompleteObjCPropertySetter(Scope *S, DeclPtrTy ClassDecl, DeclPtrTy *Methods, unsigned NumMethods); - + virtual void CodeCompleteObjCMessageReceiver(Scope *S); virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, IdentifierInfo **SelIdents, unsigned NumSelIdents); @@ -4473,6 +4575,13 @@ public: bool IsInstanceMethod, TypeTy *ReturnType, DeclPtrTy IDecl); + virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + TypeTy *ReturnType, + IdentifierInfo **SelIdents, + unsigned NumSelIdents); + //@} //===--------------------------------------------------------------------===// @@ -4491,6 +4600,9 @@ private: Action::OwningExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs); @@ -4503,7 +4615,7 @@ private: bool SemaBuiltinPrefetch(CallExpr *TheCall); bool SemaBuiltinObjectSize(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); - bool SemaBuiltinAtomicOverloaded(CallExpr *TheCall); + OwningExprResult SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult); bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); bool SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp index 444ee79..e110e3d 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAccess.cpp @@ -870,6 +870,10 @@ static void DiagnoseAccessPath(Sema &S, << BS->getSourceRange() << (BaseAccess == AS_protected) << (BS->getAccessSpecifierAsWritten() == AS_none); + + if (D) + S.Diag(D->getLocation(), diag::note_field_decl); + return; } } @@ -1020,6 +1024,9 @@ static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, if (Entity.getAccess() == AS_public) return Sema::AR_accessible; + if (S.SuppressAccessChecking) + return Sema::AR_accessible; + // If we're currently parsing a top-level declaration, delay // diagnostics. This is the only case where parsing a declaration // can actually change our effective context for the purposes of @@ -1153,9 +1160,10 @@ Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, /// Checks access to a constructor. Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, - CXXConstructorDecl *Constructor, - const InitializedEntity &Entity, - AccessSpecifier Access) { + CXXConstructorDecl *Constructor, + const InitializedEntity &Entity, + AccessSpecifier Access, + bool IsCopyBindingRefToTemp) { if (!getLangOptions().AccessControl || Access == AS_public) return AR_accessible; @@ -1166,7 +1174,9 @@ Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, QualType()); switch (Entity.getKind()) { default: - AccessEntity.setDiag(diag::err_access_ctor); + AccessEntity.setDiag(IsCopyBindingRefToTemp + ? diag::ext_rvalue_to_reference_access_ctor + : diag::err_access_ctor); break; case InitializedEntity::EK_Base: @@ -1327,3 +1337,15 @@ void Sema::CheckLookupAccess(const LookupResult &R) { } } } + +void Sema::ActOnStartSuppressingAccessChecks() { + assert(!SuppressAccessChecking && + "Tried to start access check suppression when already started."); + SuppressAccessChecking = true; +} + +void Sema::ActOnStopSuppressingAccessChecks() { + assert(SuppressAccessChecking && + "Tried to stop access check suprression when already stopped."); + SuppressAccessChecking = false; +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp index 82978c9..69f27b0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaAttr.cpp @@ -135,13 +135,24 @@ void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, return; } - // We don't support #pragma options align=power. switch (Kind) { + // For all targets we support native and natural are the same. + // + // FIXME: This is not true on Darwin/PPC. + case POAK_Native: + case POAK_Power: case POAK_Natural: Context->push(0); Context->setAlignment(0); break; + // Note that '#pragma options align=packed' is not equivalent to attribute + // packed, it has a different precedence relative to attribute aligned. + case POAK_Packed: + Context->push(0); + Context->setAlignment(1); + break; + case POAK_Mac68k: // Check if the target supports this. if (!PP.getTargetInfo().hasAlignMac68kSupport()) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp index 9b95552..b8e27e7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXCast.cpp @@ -153,7 +153,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, case tok::kw_const_cast: if (!TypeDependent) CheckConstCast(*this, Ex, DestType, OpRange, DestRange); - return Owned(new (Context) CXXConstCastExpr(DestType.getNonReferenceType(), + return Owned(new (Context) CXXConstCastExpr( + DestType.getNonLValueExprType(Context), Ex, DestTInfo, OpLoc)); case tok::kw_dynamic_cast: { @@ -161,7 +162,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, CXXBaseSpecifierArray BasePath; if (!TypeDependent) CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath); - return Owned(new (Context)CXXDynamicCastExpr(DestType.getNonReferenceType(), + return Owned(new (Context)CXXDynamicCastExpr( + DestType.getNonLValueExprType(Context), Kind, Ex, BasePath, DestTInfo, OpLoc)); } @@ -170,7 +172,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (!TypeDependent) CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind); return Owned(new (Context) CXXReinterpretCastExpr( - DestType.getNonReferenceType(), + DestType.getNonLValueExprType(Context), Kind, Ex, CXXBaseSpecifierArray(), DestTInfo, OpLoc)); } @@ -180,7 +182,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, if (!TypeDependent) CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath); - return Owned(new (Context) CXXStaticCastExpr(DestType.getNonReferenceType(), + return Owned(new (Context) CXXStaticCastExpr( + DestType.getNonLValueExprType(Context), Kind, Ex, BasePath, DestTInfo, OpLoc)); } @@ -233,6 +236,15 @@ bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { T2 = T2MPType->getPointeeType(); return true; } + + const BlockPointerType *T1BPType = T1->getAs<BlockPointerType>(), + *T2BPType = T2->getAs<BlockPointerType>(); + if (T1BPType && T2BPType) { + T1 = T1BPType->getPointeeType(); + T2 = T2BPType->getPointeeType(); + return true; + } + return false; } @@ -246,9 +258,11 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since // the rules are non-trivial. So first we construct Tcv *...cv* as described // in C++ 5.2.11p8. - assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType()) && + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType() || + SrcType->isBlockPointerType()) && "Source type is not pointer or pointer to member."); - assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) && + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType() || + DestType->isBlockPointerType()) && "Destination type is not pointer or pointer to member."); QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), @@ -257,10 +271,16 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) { // Find the qualifications. while (UnwrapDissimilarPointerTypes(UnwrappedSrcType, UnwrappedDestType)) { - cv1.push_back(UnwrappedSrcType.getQualifiers()); - cv2.push_back(UnwrappedDestType.getQualifiers()); + Qualifiers SrcQuals; + Self.Context.getUnqualifiedArrayType(UnwrappedSrcType, SrcQuals); + cv1.push_back(SrcQuals); + + Qualifiers DestQuals; + Self.Context.getUnqualifiedArrayType(UnwrappedDestType, DestQuals); + cv2.push_back(DestQuals); } - assert(cv1.size() > 0 && "Must have at least one pointer level."); + if (cv1.empty()) + return false; // Construct void pointers with those qualifiers (in reverse order of // unwrapping, of course). @@ -1014,7 +1034,7 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, // in multi-level pointers may change, but the level count must be the same, // as must be the final pointee type. while (SrcType != DestType && - Self.UnwrapSimilarPointerTypes(SrcType, DestType)) { + Self.Context.UnwrapSimilarPointerTypes(SrcType, DestType)) { Qualifiers Quals; SrcType = Self.Context.getUnqualifiedArrayType(SrcType, Quals); DestType = Self.Context.getUnqualifiedArrayType(DestType, Quals); @@ -1032,6 +1052,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, const SourceRange &OpRange, unsigned &msg, CastExpr::CastKind &Kind) { + bool IsLValueCast = false; + DestType = Self.Context.getCanonicalType(DestType); QualType SrcType = SrcExpr->getType(); if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) { @@ -1049,6 +1071,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, // This code does this transformation for the checked types. DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType()); SrcType = Self.Context.getPointerType(SrcType); + IsLValueCast = true; } // Canonicalize source for comparison. @@ -1075,13 +1098,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, } // A valid member pointer cast. - Kind = CastExpr::CK_BitCast; + Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast; return TC_Success; } // See below for the enumeral issue. - if (SrcType->isNullPtrType() && DestType->isIntegralType() && - !DestType->isEnumeralType()) { + if (SrcType->isNullPtrType() && DestType->isIntegralType(Self.Context)) { // C++0x 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. A value of std::nullptr_t can be // converted to an integral type; the conversion has the same meaning @@ -1098,9 +1120,9 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, bool destIsVector = DestType->isVectorType(); bool srcIsVector = SrcType->isVectorType(); if (srcIsVector || destIsVector) { - bool srcIsScalar = SrcType->isIntegralType() && !SrcType->isEnumeralType(); - bool destIsScalar = - DestType->isIntegralType() && !DestType->isEnumeralType(); + // FIXME: Should this also apply to floating point types? + bool srcIsScalar = SrcType->isIntegralType(Self.Context); + bool destIsScalar = DestType->isIntegralType(Self.Context); // Check if this is a cast between a vector and something else. if (!(srcIsScalar && destIsVector) && !(srcIsVector && destIsScalar) && @@ -1124,8 +1146,10 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Failed; } - bool destIsPtr = DestType->isAnyPointerType(); - bool srcIsPtr = SrcType->isAnyPointerType(); + bool destIsPtr = DestType->isAnyPointerType() || + DestType->isBlockPointerType(); + bool srcIsPtr = SrcType->isAnyPointerType() || + SrcType->isBlockPointerType(); if (!destIsPtr && !srcIsPtr) { // Except for std::nullptr_t->integer and lvalue->reference, which are // handled above, at least one of the two arguments must be a pointer. @@ -1143,9 +1167,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Success; } - // Note: Clang treats enumeration types as integral types. If this is ever - // changed for C++, the additional check here will be redundant. - if (DestType->isIntegralType() && !DestType->isEnumeralType()) { + if (DestType->isIntegralType(Self.Context)) { assert(srcIsPtr && "One type must be a pointer"); // C++ 5.2.10p4: A pointer can be explicitly converted to any integral // type large enough to hold it. @@ -1158,7 +1180,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Success; } - if (SrcType->isIntegralType() || SrcType->isEnumeralType()) { + if (SrcType->isIntegralOrEnumerationType()) { assert(destIsPtr && "One type must be a pointer"); // C++ 5.2.10p5: A value of integral or enumeration type can be explicitly // converted to a pointer. @@ -1178,14 +1200,22 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, msg = diag::err_bad_cxx_cast_const_away; return TC_Failed; } + + // Cannot convert between block pointers and Objective-C object pointers. + if ((SrcType->isBlockPointerType() && DestType->isObjCObjectPointerType()) || + (DestType->isBlockPointerType() && SrcType->isObjCObjectPointerType())) + return TC_NotApplicable; + + // Any pointer can be cast to an Objective-C pointer type with a C-style + // cast. if (CStyle && DestType->isObjCObjectPointerType()) { Kind = CastExpr::CK_AnyPointerToObjCPointerCast; return TC_Success; } - + // Not casting away constness, so the only remaining check is for compatible // pointer categories. - Kind = CastExpr::CK_BitCast; + Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast; if (SrcType->isFunctionPointerType()) { if (DestType->isFunctionPointerType()) { @@ -1211,7 +1241,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, Self.Diag(OpRange.getBegin(), diag::ext_cast_fn_obj) << OpRange; return TC_Success; } - + // C++ 5.2.10p7: A pointer to an object can be explicitly converted to // a pointer to an object of different type. // Void pointers are not specified, but supported by every compiler out there. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp index c0ec9e9..f56573a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -96,7 +96,7 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS, // injected class name of the named class template, we're entering // into that class template definition. QualType Injected - = ClassTemplate->getInjectedClassNameSpecialization(Context); + = ClassTemplate->getInjectedClassNameSpecialization(); if (Context.hasSameType(Injected, ContextType)) return ClassTemplate->getTemplatedDecl(); @@ -458,8 +458,10 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) Diag(ND->getLocation(), diag::note_previous_decl) << ND->getDeclName(); - } else + } else { Found.clear(); + Found.setLookupName(&II); + } } NamedDecl *SD = Found.getAsSingle<NamedDecl>(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp index 6fc36c2..7ccd0c5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaChecking.cpp @@ -26,7 +26,10 @@ #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h" #include "clang/Basic/TargetBuiltins.h" +#include "clang/Basic/TargetInfo.h" #include <limits> using namespace clang; @@ -199,21 +202,119 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Builtin::BI__sync_bool_compare_and_swap: case Builtin::BI__sync_lock_test_and_set: case Builtin::BI__sync_lock_release: - if (SemaBuiltinAtomicOverloaded(TheCall)) - return ExprError(); - break; - - // Target specific builtins start here. + return SemaBuiltinAtomicOverloaded(move(TheCallResult)); + } + + // Since the target specific builtins for each arch overlap, only check those + // of the arch we are compiling for. + if (BuiltinID >= Builtin::FirstTSBuiltin) { + switch (Context.Target.getTriple().getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + if (CheckARMBuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + if (CheckX86BuiltinFunctionCall(BuiltinID, TheCall)) + return ExprError(); + break; + default: + break; + } + } + + return move(TheCallResult); +} + +bool Sema::CheckX86BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + switch (BuiltinID) { case X86::BI__builtin_ia32_palignr128: case X86::BI__builtin_ia32_palignr: { llvm::APSInt Result; if (SemaBuiltinConstantArg(TheCall, 2, Result)) - return ExprError(); + return true; break; } } + return false; +} - return move(TheCallResult); +// Get the valid immediate range for the specified NEON type code. +static unsigned RFT(unsigned t, bool shift = false) { + bool quad = t & 0x10; + + switch (t & 0x7) { + case 0: // i8 + return shift ? 7 : (8 << (int)quad) - 1; + case 1: // i16 + return shift ? 15 : (4 << (int)quad) - 1; + case 2: // i32 + return shift ? 31 : (2 << (int)quad) - 1; + case 3: // i64 + return shift ? 63 : (1 << (int)quad) - 1; + case 4: // f32 + assert(!shift && "cannot shift float types!"); + return (2 << (int)quad) - 1; + case 5: // poly8 + assert(!shift && "cannot shift polynomial types!"); + return (8 << (int)quad) - 1; + case 6: // poly16 + assert(!shift && "cannot shift polynomial types!"); + return (4 << (int)quad) - 1; + case 7: // float16 + assert(!shift && "cannot shift float types!"); + return (4 << (int)quad) - 1; + } + return 0; +} + +bool Sema::CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { + llvm::APSInt Result; + + unsigned mask = 0; + unsigned TV = 0; + switch (BuiltinID) { +#define GET_NEON_OVERLOAD_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_OVERLOAD_CHECK + } + + // For NEON intrinsics which are overloaded on vector element type, validate + // the immediate which specifies which variant to emit. + if (mask) { + unsigned ArgNo = TheCall->getNumArgs()-1; + if (SemaBuiltinConstantArg(TheCall, ArgNo, Result)) + return true; + + TV = Result.getLimitedValue(32); + if ((TV > 31) || (mask & (1 << TV)) == 0) + return Diag(TheCall->getLocStart(), diag::err_invalid_neon_type_code) + << TheCall->getArg(ArgNo)->getSourceRange(); + } + + // For NEON intrinsics which take an immediate value as part of the + // instruction, range check them here. + unsigned i = 0, l = 0, u = 0; + switch (BuiltinID) { + default: return false; +#define GET_NEON_IMMEDIATE_CHECK +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_IMMEDIATE_CHECK + }; + + // Check that the immediate argument is actually a constant. + if (SemaBuiltinConstantArg(TheCall, i, Result)) + return true; + + // Range check against the upper/lower values for this isntruction. + unsigned Val = Result.getZExtValue(); + if (Val < l || Val > (u + l)) + return Diag(TheCall->getLocStart(), diag::err_argument_invalid_range) + << llvm::utostr(l) << llvm::utostr(u+l) + << TheCall->getArg(i)->getSourceRange(); + + return false; } /// CheckFunctionCall - Check a direct function call for various correctness @@ -279,32 +380,40 @@ bool Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { /// /// This function goes through and does final semantic checking for these /// builtins, -bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { +Sema::OwningExprResult +Sema::SemaBuiltinAtomicOverloaded(OwningExprResult TheCallResult) { + CallExpr *TheCall = (CallExpr *)TheCallResult.get(); DeclRefExpr *DRE =cast<DeclRefExpr>(TheCall->getCallee()->IgnoreParenCasts()); FunctionDecl *FDecl = cast<FunctionDecl>(DRE->getDecl()); // Ensure that we have at least one argument to do type inference from. - if (TheCall->getNumArgs() < 1) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1 << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); + if (TheCall->getNumArgs() < 1) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1 << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } // Inspect the first argument of the atomic builtin. This should always be // a pointer type, whose element is an integral scalar or pointer type. // Because it is a pointer type, we don't have to worry about any implicit // casts here. + // FIXME: We don't allow floating point scalars as input. Expr *FirstArg = TheCall->getArg(0); - if (!FirstArg->getType()->isPointerType()) - return Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) - << FirstArg->getType() << FirstArg->getSourceRange(); + if (!FirstArg->getType()->isPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } - QualType ValType = FirstArg->getType()->getAs<PointerType>()->getPointeeType(); + QualType ValType = + FirstArg->getType()->getAs<PointerType>()->getPointeeType(); if (!ValType->isIntegerType() && !ValType->isPointerType() && - !ValType->isBlockPointerType()) - return Diag(DRE->getLocStart(), - diag::err_atomic_builtin_must_be_pointer_intptr) - << FirstArg->getType() << FirstArg->getSourceRange(); + !ValType->isBlockPointerType()) { + Diag(DRE->getLocStart(), diag::err_atomic_builtin_must_be_pointer_intptr) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); + } // We need to figure out which concrete builtin this maps onto. For example, // __sync_fetch_and_add with a 2 byte object turns into @@ -342,8 +451,9 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { case 8: SizeIndex = 3; break; case 16: SizeIndex = 4; break; default: - return Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) - << FirstArg->getType() << FirstArg->getSourceRange(); + Diag(DRE->getLocStart(), diag::err_atomic_builtin_pointer_size) + << FirstArg->getType() << FirstArg->getSourceRange(); + return ExprError(); } // Each of these builtins has one pointer argument, followed by some number of @@ -383,12 +493,12 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { // Now that we know how many fixed arguments we expect, first check that we // have at least that many. - if (TheCall->getNumArgs() < 1+NumFixed) - return Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args_at_least) - << 0 << 1+NumFixed << TheCall->getNumArgs() - << TheCall->getCallee()->getSourceRange(); - + if (TheCall->getNumArgs() < 1+NumFixed) { + Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) + << 0 << 1+NumFixed << TheCall->getNumArgs() + << TheCall->getCallee()->getSourceRange(); + return ExprError(); + } // Get the decl for the concrete builtin from this, we can tell what the // concrete integer type we should convert to is. @@ -400,6 +510,8 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { TUScope, false, DRE->getLocStart())); const FunctionProtoType *BuiltinFT = NewBuiltinDecl->getType()->getAs<FunctionProtoType>(); + + QualType OrigValType = ValType; ValType = BuiltinFT->getArgType(0)->getAs<PointerType>()->getPointeeType(); // If the first type needs to be converted (e.g. void** -> int*), do it now. @@ -426,7 +538,7 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { CastExpr::CastKind Kind = CastExpr::CK_Unknown; CXXBaseSpecifierArray BasePath; if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath)) - return true; + return ExprError(); // Okay, we have something that *can* be converted to the right type. Check // to see if there is a potentially weird extension going on here. This can @@ -448,10 +560,30 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) { UsualUnaryConversions(PromotedCall); TheCall->setCallee(PromotedCall); - // Change the result type of the call to match the result type of the decl. - TheCall->setType(NewBuiltinDecl->getResultType()); - return false; + TheCall->setType(NewBuiltinDecl->getCallResultType()); + + // If the value type was converted to an integer when processing the + // arguments (e.g. void* -> int), we need to convert the result back. + if (!Context.hasSameUnqualifiedType(ValType, OrigValType)) { + Expr *E = TheCallResult.takeAs<Expr>(); + + assert(ValType->isIntegerType() && + "We always convert atomic operation values to integers."); + // FIXME: Handle floating point value type here too. + CastExpr::CastKind Kind; + if (OrigValType->isIntegerType()) + Kind = CastExpr::CK_IntegralCast; + else if (OrigValType->hasPointerRepresentation()) + Kind = CastExpr::CK_IntegralToPointer; + else + llvm_unreachable("Unhandled original value type!"); + + ImpCastExprToType(E, OrigValType, Kind); + return Owned(E); + } + + return move(TheCallResult); } @@ -511,7 +643,7 @@ bool Sema::SemaBuiltinVAStart(CallExpr *TheCall) { BlockScopeInfo *CurBlock = getCurBlock(); bool isVariadic; if (CurBlock) - isVariadic = CurBlock->isVariadic; + isVariadic = CurBlock->TheDecl->isVariadic(); else if (FunctionDecl *FD = getCurFunctionDecl()) isVariadic = FD->isVariadic(); else @@ -633,45 +765,54 @@ bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned NumArgs) { /// SemaBuiltinShuffleVector - Handle __builtin_shufflevector. // This is declared to take (...), so we have to check everything. Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 3) + if (TheCall->getNumArgs() < 2) return ExprError(Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 3 << TheCall->getNumArgs() + << 0 /*function call*/ << 2 << TheCall->getNumArgs() << TheCall->getSourceRange()); - unsigned numElements = std::numeric_limits<unsigned>::max(); + // Determine which of the following types of shufflevector we're checking: + // 1) unary, vector mask: (lhs, mask) + // 2) binary, vector mask: (lhs, rhs, mask) + // 3) binary, scalar mask: (lhs, rhs, index, ..., index) + QualType resType = TheCall->getArg(0)->getType(); + unsigned numElements = 0; + if (!TheCall->getArg(0)->isTypeDependent() && !TheCall->getArg(1)->isTypeDependent()) { - QualType FAType = TheCall->getArg(0)->getType(); - QualType SAType = TheCall->getArg(1)->getType(); - - if (!FAType->isVectorType() || !SAType->isVectorType()) { + QualType LHSType = TheCall->getArg(0)->getType(); + QualType RHSType = TheCall->getArg(1)->getType(); + + if (!LHSType->isVectorType() || !RHSType->isVectorType()) { Diag(TheCall->getLocStart(), diag::err_shufflevector_non_vector) << SourceRange(TheCall->getArg(0)->getLocStart(), TheCall->getArg(1)->getLocEnd()); return ExprError(); } - - if (!Context.hasSameUnqualifiedType(FAType, SAType)) { + + numElements = LHSType->getAs<VectorType>()->getNumElements(); + unsigned numResElements = TheCall->getNumArgs() - 2; + + // Check to see if we have a call with 2 vector arguments, the unary shuffle + // with mask. If so, verify that RHS is an integer vector type with the + // same number of elts as lhs. + if (TheCall->getNumArgs() == 2) { + if (!RHSType->isIntegerType() || + RHSType->getAs<VectorType>()->getNumElements() != numElements) + Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) + << SourceRange(TheCall->getArg(1)->getLocStart(), + TheCall->getArg(1)->getLocEnd()); + numResElements = numElements; + } + else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { Diag(TheCall->getLocStart(), diag::err_shufflevector_incompatible_vector) << SourceRange(TheCall->getArg(0)->getLocStart(), TheCall->getArg(1)->getLocEnd()); return ExprError(); - } - - numElements = FAType->getAs<VectorType>()->getNumElements(); - if (TheCall->getNumArgs() != numElements+2) { - if (TheCall->getNumArgs() < numElements+2) - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_few_args) - << 0 /*function call*/ - << numElements+2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); - return ExprError(Diag(TheCall->getLocEnd(), - diag::err_typecheck_call_too_many_args) - << 0 /*function call*/ - << numElements+2 << TheCall->getNumArgs() - << TheCall->getSourceRange()); + } else if (numElements != numResElements) { + QualType eltType = LHSType->getAs<VectorType>()->getElementType(); + resType = Context.getVectorType(eltType, numResElements, + VectorType::NotAltiVec); } } @@ -680,9 +821,11 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getArg(i)->isValueDependent()) continue; - llvm::APSInt Result; - if (SemaBuiltinConstantArg(TheCall, i, Result)) - return ExprError(); + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + return ExprError(Diag(TheCall->getLocStart(), + diag::err_shufflevector_nonconstant_argument) + << TheCall->getArg(i)->getSourceRange()); if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) return ExprError(Diag(TheCall->getLocStart(), @@ -698,7 +841,7 @@ Action::OwningExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { } return Owned(new (Context) ShuffleVectorExpr(Context, exprs.begin(), - exprs.size(), exprs[0]->getType(), + exprs.size(), resType, TheCall->getCallee()->getLocStart(), TheCall->getRParenLoc())); } @@ -1081,15 +1224,23 @@ public: unsigned specifierLen); private: SourceRange getFormatStringRange(); - SourceRange getFormatSpecifierRange(const char *startSpecifier, - unsigned specifierLen); + CharSourceRange getFormatSpecifierRange(const char *startSpecifier, + unsigned specifierLen); SourceLocation getLocationOfByte(const char *x); bool HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned k, const char *startSpecifier, unsigned specifierLen); - void HandleFlags(const analyze_printf::FormatSpecifier &FS, - llvm::StringRef flag, llvm::StringRef cspec, - const char *startSpecifier, unsigned specifierLen); + void HandleInvalidAmount(const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, unsigned specifierLen); + void HandleFlag(const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); + void HandleIgnoredFlag(const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, unsigned specifierLen); const Expr *getDataArg(unsigned i) const; }; @@ -1099,10 +1250,15 @@ SourceRange CheckPrintfHandler::getFormatStringRange() { return OrigFormatExpr->getSourceRange(); } -SourceRange CheckPrintfHandler:: +CharSourceRange CheckPrintfHandler:: getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) { - return SourceRange(getLocationOfByte(startSpecifier), - getLocationOfByte(startSpecifier+specifierLen-1)); + SourceLocation Start = getLocationOfByte(startSpecifier); + SourceLocation End = getLocationOfByte(startSpecifier + specifierLen - 1); + + // Advance the end SourceLocation by one due to half-open ranges. + End = End.getFileLocWithOffset(1); + + return CharSourceRange::getCharRange(Start, End); } SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) { @@ -1174,16 +1330,6 @@ const Expr *CheckPrintfHandler::getDataArg(unsigned i) const { return TheCall->getArg(FirstDataArg + i); } -void CheckPrintfHandler::HandleFlags(const analyze_printf::FormatSpecifier &FS, - llvm::StringRef flag, - llvm::StringRef cspec, - const char *startSpecifier, - unsigned specifierLen) { - const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); - S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_nonsensical_flag) - << flag << cspec << getFormatSpecifierRange(startSpecifier, specifierLen); -} - bool CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, unsigned k, const char *startSpecifier, @@ -1228,6 +1374,62 @@ CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, return true; } +void CheckPrintfHandler::HandleInvalidAmount( + const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalAmount &Amt, + unsigned type, + const char *startSpecifier, + unsigned specifierLen) { + const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); + switch (Amt.getHowSpecified()) { + case analyze_printf::OptionalAmount::Constant: + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_nonsensical_optional_amount) + << type + << CS.toString() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getFormatSpecifierRange(Amt.getStart(), + Amt.getConstantLength())); + break; + + default: + S.Diag(getLocationOfByte(Amt.getStart()), + diag::warn_printf_nonsensical_optional_amount) + << type + << CS.toString() + << getFormatSpecifierRange(startSpecifier, specifierLen); + break; + } +} + +void CheckPrintfHandler::HandleFlag(const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, + unsigned specifierLen) { + // Warn about pointless flag with a fixit removal. + const analyze_printf::ConversionSpecifier &CS = FS.getConversionSpecifier(); + S.Diag(getLocationOfByte(flag.getPosition()), + diag::warn_printf_nonsensical_flag) + << flag.toString() << CS.toString() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getFormatSpecifierRange(flag.getPosition(), 1)); +} + +void CheckPrintfHandler::HandleIgnoredFlag( + const analyze_printf::FormatSpecifier &FS, + const analyze_printf::OptionalFlag &ignoredFlag, + const analyze_printf::OptionalFlag &flag, + const char *startSpecifier, + unsigned specifierLen) { + // Warn about ignored flag with a fixit removal. + S.Diag(getLocationOfByte(ignoredFlag.getPosition()), + diag::warn_printf_ignored_flag) + << ignoredFlag.toString() << flag.toString() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getFormatSpecifierRange( + ignoredFlag.getPosition(), 1)); +} + bool CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, @@ -1315,34 +1517,57 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier return HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen); } - // Are we using '%n'? Issue a warning about this being - // a possible security issue. + // Check for invalid use of field width + if (!FS.hasValidFieldWidth()) { + HandleInvalidAmount(FS, FS.getFieldWidth(), /* field width */ 0, + startSpecifier, specifierLen); + } + + // Check for invalid use of precision + if (!FS.hasValidPrecision()) { + HandleInvalidAmount(FS, FS.getPrecision(), /* precision */ 1, + startSpecifier, specifierLen); + } + + // Check each flag does not conflict with any other component. + if (!FS.hasValidLeadingZeros()) + HandleFlag(FS, FS.hasLeadingZeros(), startSpecifier, specifierLen); + if (!FS.hasValidPlusPrefix()) + HandleFlag(FS, FS.hasPlusPrefix(), startSpecifier, specifierLen); + if (!FS.hasValidSpacePrefix()) + HandleFlag(FS, FS.hasSpacePrefix(), startSpecifier, specifierLen); + if (!FS.hasValidAlternativeForm()) + HandleFlag(FS, FS.hasAlternativeForm(), startSpecifier, specifierLen); + if (!FS.hasValidLeftJustified()) + HandleFlag(FS, FS.isLeftJustified(), startSpecifier, specifierLen); + + // Check that flags are not ignored by another flag + if (FS.hasSpacePrefix() && FS.hasPlusPrefix()) // ' ' ignored by '+' + HandleIgnoredFlag(FS, FS.hasSpacePrefix(), FS.hasPlusPrefix(), + startSpecifier, specifierLen); + if (FS.hasLeadingZeros() && FS.isLeftJustified()) // '0' ignored by '-' + HandleIgnoredFlag(FS, FS.hasLeadingZeros(), FS.isLeftJustified(), + startSpecifier, specifierLen); + + // Check the length modifier is valid with the given conversion specifier. + const LengthModifier &LM = FS.getLengthModifier(); + if (!FS.hasValidLengthModifier()) + S.Diag(getLocationOfByte(LM.getStart()), + diag::warn_printf_nonsensical_length) + << LM.toString() << CS.toString() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << FixItHint::CreateRemoval(getFormatSpecifierRange(LM.getStart(), + LM.getLength())); + + // Are we using '%n'? if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) { + // Issue a warning about this being a possible security issue. S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back) << getFormatSpecifierRange(startSpecifier, specifierLen); // Continue checking the other format specifiers. return true; } - if (CS.getKind() == ConversionSpecifier::VoidPtrArg) { - if (FS.getPrecision().getHowSpecified() != OptionalAmount::NotSpecified) - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_nonsensical_precision) - << CS.getCharacters() - << getFormatSpecifierRange(startSpecifier, specifierLen); - } - if (CS.getKind() == ConversionSpecifier::VoidPtrArg || - CS.getKind() == ConversionSpecifier::CStrArg) { - // FIXME: Instead of using "0", "+", etc., eventually get them from - // the FormatSpecifier. - if (FS.hasLeadingZeros()) - HandleFlags(FS, "0", CS.getCharacters(), startSpecifier, specifierLen); - if (FS.hasPlusPrefix()) - HandleFlags(FS, "+", CS.getCharacters(), startSpecifier, specifierLen); - if (FS.hasSpacePrefix()) - HandleFlags(FS, " ", CS.getCharacters(), startSpecifier, specifierLen); - } - // The remaining checks depend on the data arguments. if (HasVAListArg) return true; @@ -1377,11 +1602,32 @@ CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier if (ATR.matchesType(S.Context, ICE->getSubExpr()->getType())) return true; - S.Diag(getLocationOfByte(CS.getStart()), - diag::warn_printf_conversion_argument_type_mismatch) - << ATR.getRepresentativeType(S.Context) << Ex->getType() - << getFormatSpecifierRange(startSpecifier, specifierLen) - << Ex->getSourceRange(); + // We may be able to offer a FixItHint if it is a supported type. + FormatSpecifier fixedFS = FS; + bool success = fixedFS.fixType(Ex->getType()); + + if (success) { + // Get the fix string from the fixed format specifier + llvm::SmallString<128> buf; + llvm::raw_svector_ostream os(buf); + fixedFS.toString(os); + + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange() + << FixItHint::CreateReplacement( + getFormatSpecifierRange(startSpecifier, specifierLen), + os.str()); + } + else { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(); + } } return true; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp index d8c1a5c..5528875 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaCodeComplete.cpp @@ -119,10 +119,19 @@ namespace { /// nested-name-specifiers that would otherwise be filtered out. bool AllowNestedNameSpecifiers; + /// \brief If set, the type that we would prefer our resulting value + /// declarations to have. + /// + /// Closely matching the preferred type gives a boost to a result's + /// priority. + CanQualType PreferredType; + /// \brief A list of shadow maps, which is used to model name hiding at /// different levels of, e.g., the inheritance hierarchy. std::list<ShadowMap> ShadowMaps; + void AdjustResultPriorityForPreferredType(Result &R); + public: explicit ResultBuilder(Sema &SemaRef, LookupFilter Filter = 0) : SemaRef(SemaRef), Filter(Filter), AllowNestedNameSpecifiers(false) { } @@ -147,6 +156,11 @@ namespace { unsigned size() const { return Results.size(); } bool empty() const { return Results.empty(); } + /// \brief Specify the preferred type. + void setPreferredType(QualType T) { + PreferredType = SemaRef.Context.getCanonicalType(T); + } + /// \brief Specify whether nested-name-specifiers are allowed. void allowNestedNameSpecifiers(bool Allow = true) { AllowNestedNameSpecifiers = Allow; @@ -212,6 +226,7 @@ namespace { /// //@{ bool IsOrdinaryName(NamedDecl *ND) const; + bool IsOrdinaryNonTypeName(NamedDecl *ND) const; bool IsOrdinaryNonValueName(NamedDecl *ND) const; bool IsNestedNameSpecifier(NamedDecl *ND) const; bool IsEnum(NamedDecl *ND) const; @@ -222,6 +237,7 @@ namespace { bool IsType(NamedDecl *ND) const; bool IsMember(NamedDecl *ND) const; bool IsObjCIvar(NamedDecl *ND) const; + bool IsObjCMessageReceiver(NamedDecl *ND) const; //@} }; } @@ -355,8 +371,6 @@ getRequiredQualification(ASTContext &Context, Result = NestedNameSpecifier::Create(Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); - else - assert(Parent->isTranslationUnit()); } return Result; } @@ -393,13 +407,16 @@ bool ResultBuilder::isInterestingDecl(NamedDecl *ND, return false; // Filter out names reserved for the implementation (C99 7.1.3, - // C++ [lib.global.names]). Users don't need to see those. + // C++ [lib.global.names]) if they come from a system header. // // FIXME: Add predicate for this. if (Id->getLength() >= 2) { const char *Name = Id->getNameStart(); if (Name[0] == '_' && - (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z'))) + (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) && + (ND->getLocation().isInvalid() || + SemaRef.SourceMgr.isInSystemHeader( + SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))) return false; } } @@ -458,6 +475,134 @@ bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, return false; } +enum SimplifiedTypeClass { + STC_Arithmetic, + STC_Array, + STC_Block, + STC_Function, + STC_ObjectiveC, + STC_Other, + STC_Pointer, + STC_Record, + STC_Void +}; + +/// \brief A simplified classification of types used to determine whether two +/// types are "similar enough" when adjusting priorities. +static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) { + switch (T->getTypeClass()) { + case Type::Builtin: + switch (cast<BuiltinType>(T)->getKind()) { + case BuiltinType::Void: + return STC_Void; + + case BuiltinType::NullPtr: + return STC_Pointer; + + case BuiltinType::Overload: + case BuiltinType::Dependent: + case BuiltinType::UndeducedAuto: + return STC_Other; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return STC_ObjectiveC; + + default: + return STC_Arithmetic; + } + return STC_Other; + + case Type::Complex: + return STC_Arithmetic; + + case Type::Pointer: + return STC_Pointer; + + case Type::BlockPointer: + return STC_Block; + + case Type::LValueReference: + case Type::RValueReference: + return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + case Type::DependentSizedArray: + return STC_Array; + + case Type::DependentSizedExtVector: + case Type::Vector: + case Type::ExtVector: + return STC_Arithmetic; + + case Type::FunctionProto: + case Type::FunctionNoProto: + return STC_Function; + + case Type::Record: + return STC_Record; + + case Type::Enum: + return STC_Arithmetic; + + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return STC_ObjectiveC; + + default: + return STC_Other; + } +} + +/// \brief Get the type that a given expression will have if this declaration +/// is used as an expression in its "typical" code-completion form. +static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + + if (TypeDecl *Type = dyn_cast<TypeDecl>(ND)) + return C.getTypeDeclType(Type); + if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) + return C.getObjCInterfaceType(Iface); + + QualType T; + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + T = Function->getCallResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) + T = Method->getSendResultType(); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) + T = FunTmpl->getTemplatedDecl()->getCallResultType(); + else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) + T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); + else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) + T = Property->getType(); + else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) + T = Value->getType(); + else + return QualType(); + + return T.getNonReferenceType(); +} + +void ResultBuilder::AdjustResultPriorityForPreferredType(Result &R) { + QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); + if (T.isNull()) + return; + + CanQualType TC = SemaRef.Context.getCanonicalType(T); + // Check for exactly-matching types (modulo qualifiers). + if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) + R.Priority /= CCF_ExactTypeMatch; + // Check for nearly-matching types, based on classification of each. + else if ((getSimplifiedTypeClass(PreferredType) + == getSimplifiedTypeClass(TC)) && + !(PreferredType->isEnumeralType() && TC->isEnumeralType())) + R.Priority /= CCF_SimilarTypeMatch; +} + void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { assert(!ShadowMaps.empty() && "Must enter into a results scope"); @@ -542,8 +687,9 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { if (AsNestedNameSpecifier) { R.StartsNestedNameSpecifier = true; R.Priority = CCP_NestedNameSpecifier; - } - + } else if (!PreferredType.isNull()) + AdjustResultPriorityForPreferredType(R); + // If this result is supposed to have an informative qualifier, add one. if (R.QualifierIsInformative && !R.Qualifier && !R.StartsNestedNameSpecifier) { @@ -616,6 +762,9 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext, if (InBaseClass) R.Priority += CCD_InBaseClass; + if (!PreferredType.isNull()) + AdjustResultPriorityForPreferredType(R); + // Insert this result into the set of results. Results.push_back(R); } @@ -645,9 +794,11 @@ void ResultBuilder::ExitScope() { /// \brief Determines whether this given declaration will be found by /// ordinary name lookup. bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + unsigned IDNS = Decl::IDNS_Ordinary; if (SemaRef.getLangOptions().CPlusPlus) - IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND)) return true; @@ -655,14 +806,33 @@ bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const { } /// \brief Determines whether this given declaration will be found by +/// ordinary name lookup but is not a type name. +bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) + return false; + + unsigned IDNS = Decl::IDNS_Ordinary; + if (SemaRef.getLangOptions().CPlusPlus) + IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; + else if (SemaRef.getLangOptions().ObjC1 && isa<ObjCIvarDecl>(ND)) + return true; + + return ND->getIdentifierNamespace() & IDNS; +} + +/// \brief Determines whether this given declaration will be found by /// ordinary name lookup. bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const { + ND = cast<NamedDecl>(ND->getUnderlyingDecl()); + unsigned IDNS = Decl::IDNS_Ordinary; if (SemaRef.getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; return (ND->getIdentifierNamespace() & IDNS) && - !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND); + !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && + !isa<ObjCPropertyDecl>(ND); } /// \brief Determines whether the given declaration is suitable as the @@ -732,6 +902,49 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const { isa<ObjCPropertyDecl>(ND); } +static bool isObjCReceiverType(ASTContext &C, QualType T) { + T = C.getCanonicalType(T); + switch (T->getTypeClass()) { + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + return true; + + case Type::Builtin: + switch (cast<BuiltinType>(T)->getKind()) { + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + return true; + + default: + break; + } + return false; + + default: + break; + } + + if (!C.getLangOptions().CPlusPlus) + return false; + + // FIXME: We could perform more analysis here to determine whether a + // particular class type has any conversions to Objective-C types. For now, + // just accept all class types. + return T->isDependentType() || T->isRecordType(); +} + +bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const { + QualType T = getDeclUsageType(SemaRef.Context, ND); + if (T.isNull()) + return false; + + T = SemaRef.Context.getBaseElementType(T); + return isObjCReceiverType(SemaRef.Context, T); +} + + /// \rief Determines whether the given declaration is an Objective-C /// instance variable. bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const { @@ -788,27 +1001,26 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, Results.AddResult(Result("class", CCP_Type)); Results.AddResult(Result("wchar_t", CCP_Type)); - if (Results.includeCodePatterns()) { - // typename qualified-id - CodeCompletionString *Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("typename"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("qualified-id"); - Results.AddResult(Result(Pattern)); - } + // typename qualified-id + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("typename"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("qualifier"); + Pattern->AddTextChunk("::"); + Pattern->AddPlaceholderChunk("name"); + Results.AddResult(Result(Pattern)); if (LangOpts.CPlusPlus0x) { Results.AddResult(Result("auto", CCP_Type)); Results.AddResult(Result("char16_t", CCP_Type)); Results.AddResult(Result("char32_t", CCP_Type)); - if (Results.includeCodePatterns()) { - CodeCompletionString *Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("decltype"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression-or-type"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); - } + + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("decltype"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); } } @@ -819,14 +1031,18 @@ static void AddTypeSpecifierResults(const LangOptions &LangOpts, // Results.AddResult(Result("_Decimal64")); // Results.AddResult(Result("_Decimal128")); - if (Results.includeCodePatterns()) { - CodeCompletionString *Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("typeof"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression-or-type"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); - } + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("typeof"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("expression"); + Results.AddResult(Result(Pattern)); + + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("typeof"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); } } @@ -887,6 +1103,44 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts, bool NeedAt); static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); +static void AddTypedefResult(ResultBuilder &Results) { + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("typedef"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("name"); + Results.AddResult(CodeCompleteConsumer::Result(Pattern)); +} + +static bool WantTypesInContext(Action::CodeCompletionContext CCC, + const LangOptions &LangOpts) { + if (LangOpts.CPlusPlus) + return true; + + switch (CCC) { + case Action::CCC_Namespace: + case Action::CCC_Class: + case Action::CCC_ObjCInstanceVariableList: + case Action::CCC_Template: + case Action::CCC_MemberTemplate: + case Action::CCC_Statement: + case Action::CCC_RecoveryInFunction: + return true; + + case Action::CCC_ObjCInterface: + case Action::CCC_ObjCImplementation: + case Action::CCC_Expression: + case Action::CCC_Condition: + return false; + + case Action::CCC_ForInit: + return LangOpts.ObjC1 || LangOpts.C99; + } + + return false; +} + /// \brief Add language constructs that show up for "ordinary" names. static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, Scope *S, @@ -895,25 +1149,29 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, typedef CodeCompleteConsumer::Result Result; switch (CCC) { case Action::CCC_Namespace: - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { - // namespace <identifier> { } - CodeCompletionString *Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("namespace"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("identifier"); - Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); - Pattern->AddPlaceholderChunk("declarations"); - Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace); - Pattern->AddChunk(CodeCompletionString::CK_RightBrace); - Results.AddResult(Result(Pattern)); - + if (SemaRef.getLangOptions().CPlusPlus) { + CodeCompletionString *Pattern = 0; + + if (Results.includeCodePatterns()) { + // namespace <identifier> { declarations } + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("namespace"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("identifier"); + Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); + Pattern->AddPlaceholderChunk("declarations"); + Pattern->AddChunk(CodeCompletionString::CK_VerticalSpace); + Pattern->AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Pattern)); + } + // namespace identifier = identifier ; Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("namespace"); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("identifier"); + Pattern->AddPlaceholderChunk("name"); Pattern->AddChunk(CodeCompletionString::CK_Equal); - Pattern->AddPlaceholderChunk("identifier"); + Pattern->AddPlaceholderChunk("namespace"); Results.AddResult(Result(Pattern)); // Using directives @@ -933,43 +1191,49 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, Pattern->AddChunk(CodeCompletionString::CK_RightParen); Results.AddResult(Result(Pattern)); - // Explicit template instantiation - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("template"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("declaration"); - Results.AddResult(Result(Pattern)); + if (Results.includeCodePatterns()) { + // Explicit template instantiation + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("template"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("declaration"); + Results.AddResult(Result(Pattern)); + } } if (SemaRef.getLangOptions().ObjC1) AddObjCTopLevelResults(Results, true); + AddTypedefResult(Results); // Fall through case Action::CCC_Class: - if (Results.includeCodePatterns()) - Results.AddResult(Result("typedef")); - - if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { + if (SemaRef.getLangOptions().CPlusPlus) { // Using declaration CodeCompletionString *Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("using"); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("qualified-id"); + Pattern->AddPlaceholderChunk("qualifier"); + Pattern->AddTextChunk("::"); + Pattern->AddPlaceholderChunk("name"); Results.AddResult(Result(Pattern)); - // using typename qualified-id; (only in a dependent context) + // using typename qualifier::name (only in a dependent context) if (SemaRef.CurContext->isDependentContext()) { Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("using"); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); Pattern->AddTextChunk("typename"); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("qualified-id"); + Pattern->AddPlaceholderChunk("qualifier"); + Pattern->AddTextChunk("::"); + Pattern->AddPlaceholderChunk("name"); Results.AddResult(Result(Pattern)); } if (CCC == Action::CCC_Class) { + AddTypedefResult(Results); + // public: Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("public"); @@ -1025,8 +1289,7 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, case Action::CCC_RecoveryInFunction: case Action::CCC_Statement: { - if (Results.includeCodePatterns()) - Results.AddResult(Result("typedef")); + AddTypedefResult(Results); CodeCompletionString *Pattern = 0; if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) { @@ -1081,10 +1344,11 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, } // Switch-specific statements. - if (!SemaRef.getSwitchStack().empty() && Results.includeCodePatterns()) { + if (!SemaRef.getSwitchStack().empty()) { // case expression: Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk("case"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); Pattern->AddPlaceholderChunk("expression"); Pattern->AddChunk(CodeCompletionString::CK_Colon); Results.AddResult(Result(Pattern)); @@ -1178,23 +1442,21 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, } Results.AddResult(Result(Pattern)); - if (Results.includeCodePatterns()) { - // goto identifier ; - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("goto"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("identifier"); - Results.AddResult(Result(Pattern)); + // goto identifier ; + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("goto"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("label"); + Results.AddResult(Result(Pattern)); - // Using directives - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("using"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddTextChunk("namespace"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("identifier"); - Results.AddResult(Result(Pattern)); - } + // Using directives + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("using"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddTextChunk("namespace"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("identifier"); + Results.AddResult(Result(Pattern)); } // Fall through (for statement expressions). @@ -1215,132 +1477,133 @@ static void AddOrdinaryNameResults(Action::CodeCompletionContext CCC, Results.AddResult(Result("true")); Results.AddResult(Result("false")); - if (Results.includeCodePatterns()) { - // dynamic_cast < type-id > ( expression ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("dynamic_cast"); - Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_RightAngle); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); - - // static_cast < type-id > ( expression ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("static_cast"); - Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_RightAngle); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); + // dynamic_cast < type-id > ( expression ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("dynamic_cast"); + Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_RightAngle); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); + + // static_cast < type-id > ( expression ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("static_cast"); + Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_RightAngle); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // reinterpret_cast < type-id > ( expression ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("reinterpret_cast"); - Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_RightAngle); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); + // reinterpret_cast < type-id > ( expression ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("reinterpret_cast"); + Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_RightAngle); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // const_cast < type-id > ( expression ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("const_cast"); - Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_RightAngle); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); + // const_cast < type-id > ( expression ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("const_cast"); + Pattern->AddChunk(CodeCompletionString::CK_LeftAngle); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_RightAngle); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // typeid ( expression-or-type ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("typeid"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression-or-type"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); + // typeid ( expression-or-type ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("typeid"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression-or-type"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // new T ( ... ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("new"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expressions"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); + // new T ( ... ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("new"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expressions"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // new T [ ] ( ... ) - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("new"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("type-id"); - Pattern->AddChunk(CodeCompletionString::CK_LeftBracket); - Pattern->AddPlaceholderChunk("size"); - Pattern->AddChunk(CodeCompletionString::CK_RightBracket); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expressions"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); - - // delete expression - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("delete"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("expression"); - Results.AddResult(Result(Pattern)); + // new T [ ] ( ... ) + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("new"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("type"); + Pattern->AddChunk(CodeCompletionString::CK_LeftBracket); + Pattern->AddPlaceholderChunk("size"); + Pattern->AddChunk(CodeCompletionString::CK_RightBracket); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expressions"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); - // delete [] expression - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("delete"); - Pattern->AddChunk(CodeCompletionString::CK_LeftBracket); - Pattern->AddChunk(CodeCompletionString::CK_RightBracket); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("expression"); - Results.AddResult(Result(Pattern)); + // delete expression + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("delete"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("expression"); + Results.AddResult(Result(Pattern)); - // throw expression - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("throw"); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("expression"); - Results.AddResult(Result(Pattern)); - } + // delete [] expression + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("delete"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddChunk(CodeCompletionString::CK_LeftBracket); + Pattern->AddChunk(CodeCompletionString::CK_RightBracket); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("expression"); + Results.AddResult(Result(Pattern)); + + // throw expression + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("throw"); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("expression"); + Results.AddResult(Result(Pattern)); // FIXME: Rethrow? } if (SemaRef.getLangOptions().ObjC1) { // Add "super", if we're in an Objective-C class with a superclass. - if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) - if (Method->getClassInterface()->getSuperClass()) - Results.AddResult(Result("super")); - + if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { + // The interface can be NULL. + if (ObjCInterfaceDecl *ID = Method->getClassInterface()) + if (ID->getSuperClass()) + Results.AddResult(Result("super")); + } + AddObjCExpressionResults(Results, true); } - if (Results.includeCodePatterns()) { - // sizeof expression - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk("sizeof"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression-or-type"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(Result(Pattern)); - } + // sizeof expression + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk("sizeof"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression-or-type"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Results.AddResult(Result(Pattern)); break; } } - AddTypeSpecifierResults(SemaRef.getLangOptions(), Results); + if (WantTypesInContext(CCC, SemaRef.getLangOptions())) + AddTypeSpecifierResults(SemaRef.getLangOptions(), Results); if (SemaRef.getLangOptions().CPlusPlus) Results.AddResult(Result("operator")); @@ -1702,9 +1965,9 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) Keyword += II->getName().str(); Keyword += ":"; - if (Idx < StartParameter || AllParametersAreInformative) { + if (Idx < StartParameter || AllParametersAreInformative) Result->AddInformativeChunk(Keyword); - } else if (Idx == StartParameter) + else if (Idx == StartParameter) Result->AddTypedTextChunk(Keyword); else Result->AddTextChunk(Keyword); @@ -1719,14 +1982,18 @@ CodeCompleteConsumer::Result::CreateCodeCompletionString(Sema &S) { Arg = "(" + Arg + ")"; if (IdentifierInfo *II = (*P)->getIdentifier()) Arg += II->getName().str(); - if (AllParametersAreInformative) + if (DeclaringEntity) + Result->AddTextChunk(Arg); + else if (AllParametersAreInformative) Result->AddInformativeChunk(Arg); else Result->AddPlaceholderChunk(Arg); } if (Method->isVariadic()) { - if (AllParametersAreInformative) + if (DeclaringEntity) + Result->AddTextChunk(", ..."); + else if (AllParametersAreInformative) Result->AddInformativeChunk(", ..."); else Result->AddPlaceholderChunk(", ..."); @@ -1921,12 +2188,25 @@ namespace { }; } -static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results) { +static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, + bool TargetTypeIsPointer = false) { + typedef CodeCompleteConsumer::Result Result; + Results.EnterNewScope(); for (Preprocessor::macro_iterator M = PP.macro_begin(), MEnd = PP.macro_end(); - M != MEnd; ++M) - Results.AddResult(M->first); + M != MEnd; ++M) { + unsigned Priority = CCP_Macro; + + // Treat the "nil" and "NULL" macros as null pointer constants. + if (M->first->isStr("nil") || M->first->isStr("NULL")) { + Priority = CCP_Constant; + if (TargetTypeIsPointer) + Priority = Priority / CCF_SimilarTypeMatch; + } + + Results.AddResult(Result(M->first, Priority)); + } Results.ExitScope(); } @@ -1966,7 +2246,10 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, case CCC_Statement: case CCC_ForInit: case CCC_Condition: - Results.setFilter(&ResultBuilder::IsOrdinaryName); + if (WantTypesInContext(CompletionContext, getLangOptions())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); break; case CCC_RecoveryInFunction: @@ -1986,6 +2269,36 @@ void Sema::CodeCompleteOrdinaryName(Scope *S, HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } +/// \brief Perform code-completion in an expression context when we know what +/// type we're looking for. +void Sema::CodeCompleteExpression(Scope *S, QualType T) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + if (WantTypesInContext(CCC_Expression, getLangOptions())) + Results.setFilter(&ResultBuilder::IsOrdinaryName); + else + Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); + Results.setPreferredType(T.getNonReferenceType()); + + CodeCompletionDeclConsumer Consumer(Results, CurContext); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + + Results.EnterNewScope(); + AddOrdinaryNameResults(CCC_Expression, S, *this, Results); + Results.ExitScope(); + + bool PreferredTypeIsPointer = false; + if (!T.isNull()) + PreferredTypeIsPointer = T->isAnyPointerType() || + T->isMemberPointerType() || T->isBlockPointerType(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results, PreferredTypeIsPointer); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} + + static void AddObjCProperties(ObjCContainerDecl *Container, bool AllowCategories, DeclContext *CurContext, @@ -2254,6 +2567,17 @@ namespace { }; } +static bool anyNullArguments(Expr **Args, unsigned NumArgs) { + if (NumArgs && !Args) + return true; + + for (unsigned I = 0; I != NumArgs; ++I) + if (!Args[I]) + return true; + + return false; +} + void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, ExprTy **ArgsIn, unsigned NumArgs) { if (!CodeCompleter) @@ -2268,7 +2592,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, Expr **Args = (Expr **)ArgsIn; // Ignore type-dependent call expressions entirely. - if (Fn->isTypeDependent() || + if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) || Expr::hasAnyTypeDependentArguments(Args, NumArgs)) { CodeCompleteOrdinaryName(S, CCC_Expression); return; @@ -2292,7 +2616,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); if (FDecl) { - if (!FDecl->getType()->getAs<FunctionProtoType>()) + if (!getLangOptions().CPlusPlus || + !FDecl->getType()->getAs<FunctionProtoType>()) Results.push_back(ResultCandidate(FDecl)); else // FIXME: access? @@ -2302,6 +2627,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, } } + QualType ParamType; + if (!CandidateSet.empty()) { // Sort the overload candidate set by placing the best overloads first. std::stable_sort(CandidateSet.begin(), CandidateSet.end(), @@ -2314,14 +2641,85 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, if (Cand->Viable) Results.push_back(ResultCandidate(Cand->Function)); } + + // From the viable candidates, try to determine the type of this parameter. + for (unsigned I = 0, N = Results.size(); I != N; ++I) { + if (const FunctionType *FType = Results[I].getFunctionType()) + if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) + if (NumArgs < Proto->getNumArgs()) { + if (ParamType.isNull()) + ParamType = Proto->getArgType(NumArgs); + else if (!Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getArgType(NumArgs).getNonReferenceType())) { + ParamType = QualType(); + break; + } + } + } + } else { + // Try to determine the parameter type from the type of the expression + // being called. + QualType FunctionType = Fn->getType(); + if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) + FunctionType = Ptr->getPointeeType(); + else if (const BlockPointerType *BlockPtr + = FunctionType->getAs<BlockPointerType>()) + FunctionType = BlockPtr->getPointeeType(); + else if (const MemberPointerType *MemPtr + = FunctionType->getAs<MemberPointerType>()) + FunctionType = MemPtr->getPointeeType(); + + if (const FunctionProtoType *Proto + = FunctionType->getAs<FunctionProtoType>()) { + if (NumArgs < Proto->getNumArgs()) + ParamType = Proto->getArgType(NumArgs); + } } - CodeCompleteOrdinaryName(S, CCC_Expression); + if (ParamType.isNull()) + CodeCompleteOrdinaryName(S, CCC_Expression); + else + CodeCompleteExpression(S, ParamType); + if (!Results.empty()) CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(), Results.size()); } +void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) { + ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D.getAs<Decl>()); + if (!VD) { + CodeCompleteOrdinaryName(S, CCC_Expression); + return; + } + + CodeCompleteExpression(S, VD->getType()); +} + +void Sema::CodeCompleteReturn(Scope *S) { + QualType ResultType; + if (isa<BlockDecl>(CurContext)) { + if (BlockScopeInfo *BSI = getCurBlock()) + ResultType = BSI->ReturnType; + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) + ResultType = Function->getResultType(); + else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) + ResultType = Method->getResultType(); + + if (ResultType.isNull()) + CodeCompleteOrdinaryName(S, CCC_Expression); + else + CodeCompleteExpression(S, ResultType); +} + +void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { + if (LHS) + CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); + else + CodeCompleteOrdinaryName(S, CCC_Expression); +} + void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, bool EnteringContext) { if (!SS.getScopeRep() || !CodeCompleter) @@ -2460,9 +2858,6 @@ void Sema::CodeCompleteOperatorName(Scope *S) { static void AddObjCImplementationResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; // Since we have an implementation, we can end it. Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end))); @@ -2488,9 +2883,6 @@ static void AddObjCImplementationResults(const LangOptions &LangOpts, static void AddObjCInterfaceResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; // Since we have an interface or protocol, we can end it. @@ -2509,9 +2901,6 @@ static void AddObjCInterfaceResults(const LangOptions &LangOpts, } static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; CodeCompletionString *Pattern = 0; @@ -2519,31 +2908,33 @@ static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class)); Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("identifier"); - Results.AddResult(Result(Pattern)); - - // @interface name - // FIXME: Could introduce the whole pattern, including superclasses and - // such. - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface)); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("class"); + Pattern->AddPlaceholderChunk("name"); Results.AddResult(Result(Pattern)); - // @protocol name - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("protocol"); - Results.AddResult(Result(Pattern)); + if (Results.includeCodePatterns()) { + // @interface name + // FIXME: Could introduce the whole pattern, including superclasses and + // such. + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface)); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("class"); + Results.AddResult(Result(Pattern)); - // @implementation name - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation)); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddPlaceholderChunk("class"); - Results.AddResult(Result(Pattern)); + // @protocol name + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol)); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("protocol"); + Results.AddResult(Result(Pattern)); + + // @implementation name + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation)); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddPlaceholderChunk("class"); + Results.AddResult(Result(Pattern)); + } // @compatibility_alias name Pattern = new CodeCompletionString; @@ -2571,9 +2962,6 @@ void Sema::CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, } static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; CodeCompletionString *Pattern = 0; @@ -2603,31 +2991,30 @@ static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { } static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; CodeCompletionString *Pattern = 0; - // @try { statements } @catch ( declaration ) { statements } @finally - // { statements } - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try)); - Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); - Pattern->AddPlaceholderChunk("statements"); - Pattern->AddChunk(CodeCompletionString::CK_RightBrace); - Pattern->AddTextChunk("@catch"); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("parameter"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); - Pattern->AddPlaceholderChunk("statements"); - Pattern->AddChunk(CodeCompletionString::CK_RightBrace); - Pattern->AddTextChunk("@finally"); - Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); - Pattern->AddPlaceholderChunk("statements"); - Pattern->AddChunk(CodeCompletionString::CK_RightBrace); - Results.AddResult(Result(Pattern)); + if (Results.includeCodePatterns()) { + // @try { statements } @catch ( declaration ) { statements } @finally + // { statements } + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try)); + Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); + Pattern->AddPlaceholderChunk("statements"); + Pattern->AddChunk(CodeCompletionString::CK_RightBrace); + Pattern->AddTextChunk("@catch"); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("parameter"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); + Pattern->AddPlaceholderChunk("statements"); + Pattern->AddChunk(CodeCompletionString::CK_RightBrace); + Pattern->AddTextChunk("@finally"); + Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); + Pattern->AddPlaceholderChunk("statements"); + Pattern->AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Pattern)); + } // @throw Pattern = new CodeCompletionString; @@ -2636,25 +3023,24 @@ static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { Pattern->AddPlaceholderChunk("expression"); Results.AddResult(Result(Pattern)); - // @synchronized ( expression ) { statements } - Pattern = new CodeCompletionString; - Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized)); - Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); - Pattern->AddChunk(CodeCompletionString::CK_LeftParen); - Pattern->AddPlaceholderChunk("expression"); - Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); - Pattern->AddPlaceholderChunk("statements"); - Pattern->AddChunk(CodeCompletionString::CK_RightBrace); - Results.AddResult(Result(Pattern)); + if (Results.includeCodePatterns()) { + // @synchronized ( expression ) { statements } + Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized)); + Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); + Pattern->AddChunk(CodeCompletionString::CK_LeftParen); + Pattern->AddPlaceholderChunk("expression"); + Pattern->AddChunk(CodeCompletionString::CK_RightParen); + Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); + Pattern->AddPlaceholderChunk("statements"); + Pattern->AddChunk(CodeCompletionString::CK_RightBrace); + Results.AddResult(Result(Pattern)); + } } static void AddObjCVisibilityResults(const LangOptions &LangOpts, ResultBuilder &Results, bool NeedAt) { - if (!Results.includeCodePatterns()) - return; - typedef CodeCompleteConsumer::Result Result; Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private))); Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected))); @@ -3021,6 +3407,31 @@ static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { .Default(0); } +void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + // Find anything that looks like it could be a message receiver. + Results.setFilter(&ResultBuilder::IsObjCMessageReceiver); + CodeCompletionDeclConsumer Consumer(Results, CurContext); + Results.EnterNewScope(); + LookupVisibleDecls(S, LookupOrdinaryName, Consumer); + + // If we are in an Objective-C method inside a class that has a superclass, + // add "super" as an option. + if (ObjCMethodDecl *Method = getCurMethodDecl()) + if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) + if (Iface->getSuperClass()) + Results.AddResult(Result("super")); + + Results.ExitScope(); + + if (CodeCompleter->includeMacros()) + AddMacroResults(PP, Results); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); + +} + void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, IdentifierInfo **SelIdents, unsigned NumSelIdents) { @@ -3113,9 +3524,9 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, TypeTy *Receiver, // If we have an external source, load the entire class method // pool from the PCH file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetSelector(I); + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || FactoryMethodPool.count(Sel) || InstanceMethodPool.count(Sel)) continue; @@ -3214,9 +3625,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // If we have an external source, load the entire class method // pool from the PCH file. if (ExternalSource) { - for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; - ++I) { - Selector Sel = ExternalSource->GetSelector(I); + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); if (Sel.isNull() || InstanceMethodPool.count(Sel) || FactoryMethodPool.count(Sel)) continue; @@ -3550,14 +3961,11 @@ static void FindImplementableMethods(ASTContext &Context, // Add methods from any class extensions (but not from categories; // those should go into category implementations). - for (ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat; - Cat = Cat->getNextClassCategory()) { - if (!Cat->IsClassExtension()) - continue; - - FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType, + for (const ObjCCategoryDecl *Cat = IFace->getFirstClassExtension(); Cat; + Cat = Cat->getNextClassExtension()) + FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat), + WantInstanceMethods, ReturnType, IsInImplementation, KnownMethods); - } } if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { @@ -3714,7 +4122,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, Pattern->AddTextChunk("..."); } - if (IsInImplementation) { + if (IsInImplementation && Results.includeCodePatterns()) { // We will be defining the method here, so add a compound statement. Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace); Pattern->AddChunk(CodeCompletionString::CK_LeftBrace); @@ -3739,3 +4147,70 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S, HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); } + +void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + TypeTy *ReturnTy, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { + llvm::DenseMap<Selector, ObjCMethodList> &Pool + = IsInstanceMethod? InstanceMethodPool : FactoryMethodPool; + + // If we have an external source, load the entire class method + // pool from the PCH file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); + I != N; ++I) { + Selector Sel = ExternalSource->GetExternalSelector(I); + if (Sel.isNull() || InstanceMethodPool.count(Sel) || + FactoryMethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel, IsInstanceMethod); + } + } + + // Build the set of methods we can see. + typedef CodeCompleteConsumer::Result Result; + ResultBuilder Results(*this); + + if (ReturnTy) + Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); + + Results.EnterNewScope(); + for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = Pool.begin(), + MEnd = Pool.end(); + M != MEnd; + ++M) { + for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; + MethList = MethList->Next) { + if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, + NumSelIdents)) + continue; + + if (AtParameterName) { + // Suggest parameter names we've seen before. + if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { + ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; + if (Param->getIdentifier()) { + CodeCompletionString *Pattern = new CodeCompletionString; + Pattern->AddTypedTextChunk(Param->getIdentifier()->getName()); + Results.AddResult(Pattern); + } + } + + continue; + } + + Result R(MethList->Method, 0); + R.StartParameter = NumSelIdents; + R.AllParametersAreInformative = false; + R.DeclaringEntity = true; + Results.MaybeAddResult(R, CurContext); + } + } + + Results.ExitScope(); + HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size()); +} diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp index af02099..c1c898f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -87,8 +87,8 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (!isClassName) return 0; - // We know from the grammar that this name refers to a type, so build a - // DependentNameType node to describe the type. + // We know from the grammar that this name refers to a type, + // so build a dependent node to describe the type. return CheckTypenameType(ETK_None, (NestedNameSpecifier *)SS->getScopeRep(), II, SourceLocation(), SS->getRange(), NameLoc @@ -196,12 +196,6 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { T = Context.getObjCInterfaceType(IDecl); - } else if (UnresolvedUsingTypenameDecl *UUDecl = - dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) { - // FIXME: preserve source structure information. - T = Context.getDependentNameType(ETK_None, - UUDecl->getTargetNestedNameSpecifier(), - &II); } else { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); @@ -313,7 +307,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, << (NestedNameSpecifier *)SS->getScopeRep() << II.getName() << SourceRange(SS->getRange().getBegin(), IILoc) << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename "); - SuggestedType = ActOnTypenameType(SourceLocation(), *SS, II, IILoc).get(); + SuggestedType = ActOnTypenameType(S, SourceLocation(), *SS, II, IILoc).get(); } else { assert(SS && SS->isInvalid() && "Invalid scope specifier has already been diagnosed"); @@ -959,7 +953,7 @@ Sema::CXXSpecialMember Sema::getSpecialMember(const CXXMethodDecl *MD) { return Sema::CXXCopyAssignment; } -/// canREdefineFunction - checks if a function can be redefined. Currently, +/// canRedefineFunction - checks if a function can be redefined. Currently, /// only extern inline functions can be redefined, and even then only in /// GNU89 mode. static bool canRedefineFunction(const FunctionDecl *FD, @@ -1063,13 +1057,27 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } // FIXME: diagnose the other way around? - if (OldType->getNoReturnAttr() && - !NewType->getNoReturnAttr()) { + if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) { NewQType = Context.getNoReturnType(NewQType); New->setType(NewQType); assert(NewQType.isCanonical()); } + // Merge regparm attribute. + if (OldType->getRegParmType() != NewType->getRegParmType()) { + if (NewType->getRegParmType()) { + Diag(New->getLocation(), diag::err_regparm_mismatch) + << NewType->getRegParmType() + << OldType->getRegParmType(); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + NewQType = Context.getRegParmType(NewQType, OldType->getRegParmType()); + New->setType(NewQType); + assert(NewQType.isCanonical()); + } + if (getLangOptions().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: @@ -1446,6 +1454,17 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { New->setInvalidDecl(); return; } + // c99 6.2.2 P4. + // For an identifier declared with the storage-class specifier extern in a + // scope in which a prior declaration of that identifier is visible, if + // the prior declaration specifies internal or external linkage, the linkage + // of the identifier at the later declaration is the same as the linkage + // specified at the prior declaration. + // FIXME. revisit this code. + if (New->hasExternalStorage() && + Old->getLinkage() == InternalLinkage && + New->getDeclContext() == Old->getDeclContext()) + New->setStorageClass(Old->getStorageClass()); // Keep a chain of previous declarations. New->setPreviousDeclaration(Old); @@ -1520,6 +1539,14 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, return DeclPtrTy::make(Tag); } + if (getLangOptions().CPlusPlus && + DS.getStorageClassSpec() != DeclSpec::SCS_typedef) + if (EnumDecl *Enum = dyn_cast_or_null<EnumDecl>(Tag)) + if (Enum->enumerator_begin() == Enum->enumerator_end() && + !Enum->getIdentifier() && !Enum->isInvalidDecl()) + Diag(Enum->getLocation(), diag::ext_no_declarators) + << DS.getSourceRange(); + if (!DS.isMissingDeclaratorOk() && DS.getTypeSpecType() != DeclSpec::TST_error) { // Warn about typedefs of enums without names, since this is an @@ -1770,6 +1797,8 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, << (int)Record->isUnion(); Invalid = true; } + } else if (isa<AccessSpecDecl>(*Mem)) { + // Any access specifier is fine. } else { // We have something that isn't a non-static data // member. Complain about it. @@ -1795,8 +1824,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Mock up a declarator. Declarator Dc(DS, Declarator::TypeNameContext); - TypeSourceInfo *TInfo = 0; - GetTypeForDeclarator(Dc, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(Dc, S); assert(TInfo && "couldn't build declarator info for anonymous struct/union"); // Create a declaration for this anonymous struct/union. @@ -2091,8 +2119,8 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, NamedDecl *New; - TypeSourceInfo *TInfo = 0; - QualType R = GetTypeForDeclarator(D, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType R = TInfo->getType(); LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName, ForRedeclaration); @@ -2342,6 +2370,12 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isThreadSpecified()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_invalid_thread); + if (D.getName().Kind != UnqualifiedId::IK_Identifier) { + Diag(D.getName().StartLocation, diag::err_typedef_not_identifier) + << D.getName().getSourceRange(); + return 0; + } + TypedefDecl *NewTD = ParseTypedefDecl(S, D, R, TInfo); if (!NewTD) return 0; @@ -2537,6 +2571,8 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Match up the template parameter lists with the scope specifier, then // determine whether we have a template or a template specialization. bool isExplicitSpecialization = false; + unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); + bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), @@ -2544,7 +2580,11 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, (TemplateParameterList**)TemplateParamLists.get(), TemplateParamLists.size(), /*never a friend*/ false, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { + // All but one template parameter lists have been matching. + --NumMatchedTemplateParamLists; + if (TemplateParams->size() > 0) { // There is no such thing as a variable template. Diag(D.getIdentifierLoc(), diag::err_template_variable) @@ -2568,11 +2608,17 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, VarDecl *NewVD = VarDecl::Create(Context, DC, D.getIdentifierLoc(), II, R, TInfo, SC, SCAsWritten); - if (D.isInvalidType()) + if (D.isInvalidType() || Invalid) NewVD->setInvalidDecl(); SetNestedNameSpecifier(NewVD, D); + if (NumMatchedTemplateParamLists > 0) { + NewVD->setTemplateParameterListsInfo(Context, + NumMatchedTemplateParamLists, + (TemplateParameterList**)TemplateParamLists.release()); + } + if (D.getDeclSpec().isThreadSpecified()) { if (NewVD->hasLocalStorage()) Diag(D.getDeclSpec().getThreadSpecLoc(), diag::err_thread_non_global); @@ -2831,6 +2877,23 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, return NewVD->setInvalidDecl(); } + // Function pointers and references cannot have qualified function type, only + // function pointer-to-members can do that. + QualType Pointee; + unsigned PtrOrRef = 0; + if (const PointerType *Ptr = T->getAs<PointerType>()) + Pointee = Ptr->getPointeeType(); + else if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { + Pointee = Ref->getPointeeType(); + PtrOrRef = 1; + } + if (!Pointee.isNull() && Pointee->isFunctionProtoType() && + Pointee->getAs<FunctionProtoType>()->getTypeQuals() != 0) { + Diag(NewVD->getLocation(), diag::err_invalid_qualified_function_pointer) + << PtrOrRef; + return NewVD->setInvalidDecl(); + } + if (!Previous.empty()) { Redeclaration = true; MergeVarDecl(NewVD, Previous); @@ -2858,7 +2921,7 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, // FIXME: Do we care about other names here too? if (Name.getNameKind() == DeclarationName::CXXDestructorName) { - // We really want to find the base class constructor here. + // We really want to find the base class destructor here. QualType T = Data->S->Context.getTypeDeclType(BaseRecord); CanQualType CT = Data->S->Context.getCanonicalType(T); @@ -2868,8 +2931,9 @@ static bool FindOverriddenMethod(const CXXBaseSpecifier *Specifier, for (Path.Decls = BaseRecord->lookup(Name); Path.Decls.first != Path.Decls.second; ++Path.Decls.first) { - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) { - if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD)) + NamedDecl *D = *Path.Decls.first; + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, false)) return true; } } @@ -2992,7 +3056,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. if (DC->isRecord()) { - R = CheckDestructorDeclarator(D, SC); + R = CheckDestructorDeclarator(D, R, SC); NewFD = CXXDestructorDecl::Create(Context, cast<CXXRecordDecl>(DC), @@ -3093,6 +3157,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; + unsigned NumMatchedTemplateParamLists = TemplateParamLists.size(); + bool Invalid = false; if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), @@ -3100,7 +3166,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, (TemplateParameterList**)TemplateParamLists.get(), TemplateParamLists.size(), isFriend, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { + // All but one template parameter lists have been matching. + --NumMatchedTemplateParamLists; + if (TemplateParams->size() > 0) { // This is a function template @@ -3140,9 +3210,18 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << FixItHint::CreateInsertion(InsertLoc, "<>"); } } + } - // FIXME: Free this memory properly. - TemplateParamLists.release(); + if (NumMatchedTemplateParamLists > 0) { + NewFD->setTemplateParameterListsInfo(Context, + NumMatchedTemplateParamLists, + (TemplateParameterList**)TemplateParamLists.release()); + } + + if (Invalid) { + NewFD->setInvalidDecl(); + if (FunctionTemplate) + FunctionTemplate->setInvalidDecl(); } // C++ [dcl.fct.spec]p5: @@ -3272,14 +3351,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Synthesize a parameter for each argument type. for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(), AE = FT->arg_type_end(); AI != AE; ++AI) { - ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD, - D.getIdentifierLoc(), 0, - *AI, - Context.getTrivialTypeSourceInfo(*AI, - D.getIdentifierLoc()), - VarDecl::None, - VarDecl::None, 0); - Param->setImplicit(); + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI); Params.push_back(Param); } } else { @@ -3456,7 +3529,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Redeclaration && Previous.isSingleResult()) { const FunctionDecl *Def; FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl()); - if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) { + if (PrevFD && PrevFD->hasBody(Def) && D.hasAttributes()) { Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); } @@ -3582,13 +3655,10 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, } } - switch (CheckOverload(NewFD, Previous, OldDecl)) { + switch (CheckOverload(S, NewFD, Previous, OldDecl, + /*NewIsUsingDecl*/ false)) { case Ovl_Match: Redeclaration = true; - if (isa<UsingShadowDecl>(OldDecl) && CurContext->isRecord()) { - HideUsingShadowDecl(S, cast<UsingShadowDecl>(OldDecl)); - Redeclaration = false; - } break; case Ovl_NonFunction: @@ -3647,7 +3717,7 @@ void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, CXXRecordDecl *Record = Destructor->getParent(); QualType ClassType = Context.getTypeDeclType(Record); - // FIXME: Shouldn't we be able to perform thisc heck even when the class + // FIXME: Shouldn't we be able to perform this check even when the class // type is dependent? Both gcc and edg can handle that. if (!ClassType->isDependentType()) { DeclarationName Name @@ -3943,7 +4013,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { QualType T = VDecl->getType(); if (!T->isDependentType() && (!Context.getCanonicalType(T).isConstQualified() || - !T->isIntegralType())) { + !T->isIntegralOrEnumerationType())) { Diag(VDecl->getLocation(), diag::err_member_initialization) << VDecl->getDeclName() << Init->getSourceRange(); VDecl->setInvalidDecl(); @@ -3954,7 +4024,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // can specify a constant-initializer which shall be an // integral constant expression (5.19). if (!Init->isTypeDependent() && - !Init->getType()->isIntegralType()) { + !Init->getType()->isIntegralOrEnumerationType()) { // We have a non-dependent, non-integral or enumeration type. Diag(Init->getSourceRange().getBegin(), diag::err_in_class_initializer_non_integral_type) @@ -4264,9 +4334,9 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); - TypeSourceInfo *TInfo = 0; TagDecl *OwnedDecl = 0; - QualType parmDeclType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl); + QualType parmDeclType = TInfo->getType(); if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { // C++ [dcl.fct]p6: @@ -4331,6 +4401,18 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { return DeclPtrTy::make(New); } +/// \brief Synthesizes a variable for a parameter arising from a +/// typedef. +ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC, + SourceLocation Loc, + QualType T) { + ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0, + T, Context.getTrivialTypeSourceInfo(T, Loc), + VarDecl::None, VarDecl::None, 0); + Param->setImplicit(); + return Param; +} + ParmVarDecl *Sema::CheckParameter(DeclContext *DC, TypeSourceInfo *TSInfo, QualType T, IdentifierInfo *Name, @@ -4489,7 +4571,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // But don't complain if we're in GNU89 mode and the previous definition // was an extern inline function. const FunctionDecl *Definition; - if (FD->getBody(Definition) && + if (FD->hasBody(Definition) && !canRedefineFunction(Definition, getLangOptions())) { Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); Diag(Definition->getLocation(), diag::note_previous_definition); @@ -4964,16 +5046,25 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Check explicit specializations more carefully. bool isExplicitSpecialization = false; + unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); + bool Invalid = false; if (TUK != TUK_Reference) { if (TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(KWLoc, SS, (TemplateParameterList**)TemplateParameterLists.get(), TemplateParameterLists.size(), TUK == TUK_Friend, - isExplicitSpecialization)) { + isExplicitSpecialization, + Invalid)) { + // All but one template parameter lists have been matching. + --NumMatchedTemplateParamLists; + if (TemplateParams->size() > 0) { // This is a declaration or definition of a class template (which may // be a member of another template). + if (Invalid) + return DeclPtrTy(); + OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attr, @@ -4988,14 +5079,11 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, isExplicitSpecialization = true; } } - - TemplateParameterLists.release(); } DeclContext *SearchDC = CurContext; DeclContext *DC = CurContext; bool isStdBadAlloc = false; - bool Invalid = false; RedeclarationKind Redecl = ForRedeclaration; if (TUK == TUK_Friend || TUK == TUK_Reference) @@ -5231,7 +5319,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // for the consumer of this Decl to know it doesn't own it. // For our current ASTs this shouldn't be a problem, but will // need to be changed with DeclGroups. - if (TUK == TUK_Reference || TUK == TUK_Friend) + if ((TUK == TUK_Reference && !PrevTagDecl->getFriendObjectKind()) || + TUK == TUK_Friend) return DeclPtrTy::make(PrevTagDecl); // Diagnose attempts to redefine a tag. @@ -5364,10 +5453,17 @@ CreateNewDecl: New = EnumDecl::Create(Context, SearchDC, Loc, Name, KWLoc, cast_or_null<EnumDecl>(PrevDecl)); // If this is an undefined enum, warn. - if (TUK != TUK_Definition && !Invalid) { - unsigned DK = getLangOptions().CPlusPlus? diag::err_forward_ref_enum - : diag::ext_forward_ref_enum; - Diag(Loc, DK); + if (TUK != TUK_Definition && !Invalid) { + TagDecl *Def; + if (PrevDecl && (Def = cast<EnumDecl>(PrevDecl)->getDefinition())) { + Diag(Loc, diag::ext_forward_ref_enum_def) + << New; + Diag(Def->getLocation(), diag::note_previous_definition); + } else { + Diag(Loc, + getLangOptions().CPlusPlus? diag::err_forward_ref_enum + : diag::ext_forward_ref_enum); + } } } else { // struct/union/class @@ -5392,6 +5488,11 @@ CreateNewDecl: NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); New->setQualifierInfo(NNS, SS.getRange()); + if (NumMatchedTemplateParamLists > 0) { + New->setTemplateParameterListsInfo(Context, + NumMatchedTemplateParamLists, + (TemplateParameterList**) TemplateParameterLists.release()); + } } else Invalid = true; @@ -5547,7 +5648,7 @@ bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName, // C99 6.7.2.1p4 - verify the field type. // C++ 9.6p3: A bit-field shall have integral or enumeration type. - if (!FieldTy->isDependentType() && !FieldTy->isIntegralType()) { + if (!FieldTy->isDependentType() && !FieldTy->isIntegralOrEnumerationType()) { // Handle incomplete types with specific error. if (RequireCompleteType(FieldLoc, FieldTy, diag::err_field_incomplete)) return true; @@ -5629,8 +5730,8 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, SourceLocation Loc = DeclStart; if (II) Loc = D.getIdentifierLoc(); - TypeSourceInfo *TInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); @@ -5740,6 +5841,24 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, ZeroWidth = false; } + // Check that 'mutable' is consistent with the type of the declaration. + if (!InvalidDecl && Mutable) { + unsigned DiagID = 0; + if (T->isReferenceType()) + DiagID = diag::err_mutable_reference; + else if (T.isConstQualified()) + DiagID = diag::err_mutable_const; + + if (DiagID) { + SourceLocation ErrLoc = Loc; + if (D && D->getDeclSpec().getStorageClassSpecLoc().isValid()) + ErrLoc = D->getDeclSpec().getStorageClassSpecLoc(); + Diag(ErrLoc, DiagID); + Mutable = false; + InvalidDecl = true; + } + } + FieldDecl *NewFD = FieldDecl::Create(Context, Record, Loc, II, T, TInfo, BitWidth, Mutable); if (InvalidDecl) @@ -5761,41 +5880,42 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (const RecordType *RT = EltTy->getAs<RecordType>()) { CXXRecordDecl* RDecl = cast<CXXRecordDecl>(RT->getDecl()); - - if (!RDecl->hasTrivialConstructor()) - CXXRecord->setHasTrivialConstructor(false); - if (!RDecl->hasTrivialCopyConstructor()) - CXXRecord->setHasTrivialCopyConstructor(false); - if (!RDecl->hasTrivialCopyAssignment()) - CXXRecord->setHasTrivialCopyAssignment(false); - if (!RDecl->hasTrivialDestructor()) - CXXRecord->setHasTrivialDestructor(false); - - // C++ 9.5p1: An object of a class with a non-trivial - // constructor, a non-trivial copy constructor, a non-trivial - // destructor, or a non-trivial copy assignment operator - // cannot be a member of a union, nor can an array of such - // objects. - // TODO: C++0x alters this restriction significantly. - if (Record->isUnion()) { - // We check for copy constructors before constructors - // because otherwise we'll never get complaints about - // copy constructors. - - CXXSpecialMember member = CXXInvalid; + if (RDecl->getDefinition()) { + if (!RDecl->hasTrivialConstructor()) + CXXRecord->setHasTrivialConstructor(false); if (!RDecl->hasTrivialCopyConstructor()) - member = CXXCopyConstructor; - else if (!RDecl->hasTrivialConstructor()) - member = CXXConstructor; - else if (!RDecl->hasTrivialCopyAssignment()) - member = CXXCopyAssignment; - else if (!RDecl->hasTrivialDestructor()) - member = CXXDestructor; - - if (member != CXXInvalid) { - Diag(Loc, diag::err_illegal_union_member) << Name << member; - DiagnoseNontrivial(RT, member); - NewFD->setInvalidDecl(); + CXXRecord->setHasTrivialCopyConstructor(false); + if (!RDecl->hasTrivialCopyAssignment()) + CXXRecord->setHasTrivialCopyAssignment(false); + if (!RDecl->hasTrivialDestructor()) + CXXRecord->setHasTrivialDestructor(false); + + // C++ 9.5p1: An object of a class with a non-trivial + // constructor, a non-trivial copy constructor, a non-trivial + // destructor, or a non-trivial copy assignment operator + // cannot be a member of a union, nor can an array of such + // objects. + // TODO: C++0x alters this restriction significantly. + if (Record->isUnion()) { + // We check for copy constructors before constructors + // because otherwise we'll never get complaints about + // copy constructors. + + CXXSpecialMember member = CXXInvalid; + if (!RDecl->hasTrivialCopyConstructor()) + member = CXXCopyConstructor; + else if (!RDecl->hasTrivialConstructor()) + member = CXXConstructor; + else if (!RDecl->hasTrivialCopyAssignment()) + member = CXXCopyAssignment; + else if (!RDecl->hasTrivialDestructor()) + member = CXXDestructor; + + if (member != CXXInvalid) { + Diag(Loc, diag::err_illegal_union_member) << Name << member; + DiagnoseNontrivial(RT, member); + NewFD->setInvalidDecl(); + } } } } @@ -5842,7 +5962,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { typedef CXXRecordDecl::ctor_iterator ctor_iter; for (ctor_iter ci = RD->ctor_begin(), ce = RD->ctor_end(); ci != ce;++ci){ const FunctionDecl *body = 0; - ci->getBody(body); + ci->hasBody(body); if (!body || !cast<CXXConstructorDecl>(body)->isImplicitlyDefined()) { SourceLocation CtorLoc = ci->getLocation(); Diag(CtorLoc, diag::note_nontrivial_user_defined) << QT << member; @@ -5876,7 +5996,7 @@ void Sema::DiagnoseNontrivial(const RecordType* T, CXXSpecialMember member) { case CXXDestructor: if (RD->hasUserDeclaredDestructor()) { - SourceLocation DtorLoc = RD->getDestructor(Context)->getLocation(); + SourceLocation DtorLoc = LookupDestructor(RD)->getLocation(); Diag(DtorLoc, diag::note_nontrivial_user_defined) << QT << member; return; } @@ -5985,8 +6105,8 @@ Sema::DeclPtrTy Sema::ActOnIvar(Scope *S, // FIXME: Unnamed fields can be handled in various different ways, for // example, unnamed unions inject all members into the struct namespace! - TypeSourceInfo *TInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); if (BitWidth) { // 6.7.2.1p3, 6.7.2.1p4 @@ -6188,6 +6308,12 @@ void Sema::ActOnFields(Scope* S, (FD->getType()->isObjCObjectPointerType() || FD->getType().isObjCGCStrong())) Record->setHasObjectMember(true); + else if (Context.getAsArrayType(FD->getType())) { + QualType BaseType = Context.getBaseElementType(FD->getType()); + if (Record && BaseType->isRecordType() && + BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()) + Record->setHasObjectMember(true); + } // Keep track of the number of named members. if (FD->getIdentifier()) ++NumNamedMembers; @@ -6241,7 +6367,7 @@ void Sema::ActOnFields(Scope* S, static bool isRepresentableIntegerValue(ASTContext &Context, llvm::APSInt &Value, QualType T) { - assert(T->isIntegralType() && "Integral type required!"); + assert(T->isIntegralType(Context) && "Integral type required!"); unsigned BitWidth = Context.getIntWidth(T); if (Value.isUnsigned() || Value.isNonNegative()) @@ -6255,7 +6381,7 @@ static bool isRepresentableIntegerValue(ASTContext &Context, static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { // FIXME: Int128/UInt128 support, which also needs to be introduced into // enum checking below. - assert(T->isIntegralType() && "Integral type required!"); + assert(T->isIntegralType(Context) && "Integral type required!"); const unsigned NumTypes = 4; QualType SignedIntegralTypes[NumTypes] = { Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp index c6dcc3b..3b82f58 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -913,7 +913,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (VarDecl *VD = dyn_cast<VarDecl>(D)) { isDef = (!VD->hasExternalStorage() || VD->getInit()); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - isDef = FD->getBody(); + isDef = FD->hasBody(); } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) { // We ignore weak import on properties and methods return; @@ -1180,6 +1180,54 @@ static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) { return InvalidFormat; } +/// Handle __attribute__((init_priority(priority))) attributes based on +/// http://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html +static void HandleInitPriorityAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + if (!S.getLangOptions().CPlusPlus) { + S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + return; + } + + if (!isa<VarDecl>(d) || S.getCurFunctionOrMethodDecl()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + QualType T = dyn_cast<VarDecl>(d)->getType(); + if (S.Context.getAsArrayType(T)) + T = S.Context.getBaseElementType(T); + if (!T->getAs<RecordType>()) { + S.Diag(Attr.getLoc(), diag::err_init_priority_object_attr); + Attr.setInvalid(); + return; + } + + if (Attr.getNumArgs() != 1) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + Attr.setInvalid(); + return; + } + Expr *priorityExpr = static_cast<Expr *>(Attr.getArg(0)); + + llvm::APSInt priority(32); + if (priorityExpr->isTypeDependent() || priorityExpr->isValueDependent() || + !priorityExpr->isIntegerConstantExpr(priority, S.Context)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) + << "init_priority" << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + unsigned prioritynum = priority.getZExtValue(); + if (prioritynum < 101 || prioritynum > 65535) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_outof_range) + << priorityExpr->getSourceRange(); + Attr.setInvalid(); + return; + } + d->addAttr(::new (S.Context) InitPriorityAttr(prioritynum)); +} + /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1362,9 +1410,10 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, FieldDecl *FirstField = *Field; QualType FirstType = FirstField->getType(); - if (FirstType->isFloatingType() || FirstType->isVectorType()) { + if (FirstType->hasFloatingRepresentation() || FirstType->isVectorType()) { S.Diag(FirstField->getLocation(), - diag::warn_transparent_union_attribute_floating); + diag::warn_transparent_union_attribute_floating) + << FirstType->isVectorType() << FirstType; return; } @@ -1410,7 +1459,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString())); } -static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static void HandleAlignedAttr(Decl *D, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() > 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; @@ -1421,30 +1470,36 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // than GNU's, and should error out when it is used to specify a // weaker alignment, rather than being silently ignored. - unsigned Align = 0; if (Attr.getNumArgs() == 0) { // FIXME: This should be the target specific maximum alignment. // (For now we just use 128 bits which is the maximum on X86). - Align = 128; - d->addAttr(::new (S.Context) AlignedAttr(Align)); + D->addAttr(::new (S.Context) AlignedAttr(128)); + return; + } + + S.AddAlignedAttr(Attr.getLoc(), D, static_cast<Expr *>(Attr.getArg(0))); +} + +void Sema::AddAlignedAttr(SourceLocation AttrLoc, Decl *D, Expr *E) { + if (E->isTypeDependent() || E->isValueDependent()) { + // Save dependent expressions in the AST to be instantiated. + D->addAttr(::new (Context) AlignedAttr(E)); return; } - Expr *alignmentExpr = static_cast<Expr *>(Attr.getArg(0)); llvm::APSInt Alignment(32); - if (alignmentExpr->isTypeDependent() || alignmentExpr->isValueDependent() || - !alignmentExpr->isIntegerConstantExpr(Alignment, S.Context)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int) - << "aligned" << alignmentExpr->getSourceRange(); + if (!E->isIntegerConstantExpr(Alignment, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_not_int) + << "aligned" << E->getSourceRange(); return; } if (!llvm::isPowerOf2_64(Alignment.getZExtValue())) { - S.Diag(Attr.getLoc(), diag::err_attribute_aligned_not_power_of_two) - << alignmentExpr->getSourceRange(); + Diag(AttrLoc, diag::err_attribute_aligned_not_power_of_two) + << E->getSourceRange(); return; } - d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); + D->addAttr(::new (Context) AlignedAttr(Alignment.getZExtValue() * 8)); } /// HandleModeAttr - This attribute modifies the width of a decl with primitive @@ -1525,7 +1580,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (!OldTy->getAs<BuiltinType>() && !OldTy->isComplexType()) S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); else if (IntegerMode) { - if (!OldTy->isIntegralType()) + if (!OldTy->isIntegralOrEnumerationType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else if (ComplexMode) { if (!OldTy->isComplexType()) @@ -1650,6 +1705,23 @@ static void HandleNoInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) NoInlineAttr()); } +static void HandleNoInstrumentFunctionAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + // check the attribute arguments. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return; + } + + if (!isa<FunctionDecl>(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << 0 /*function*/; + return; + } + + d->addAttr(::new (S.Context) NoInstrumentFunctionAttr()); +} + static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { @@ -1951,6 +2023,9 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_reqd_wg_size: HandleReqdWorkGroupSize(D, Attr, S); break; + case AttributeList::AT_init_priority: + HandleInitPriorityAttr(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_unavailable: HandleUnavailableAttr (D, Attr, S); break; @@ -1979,9 +2054,11 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_noinline: HandleNoInlineAttr (D, Attr, S); break; case AttributeList::AT_regparm: HandleRegparmAttr (D, Attr, S); break; case AttributeList::IgnoredAttribute: - case AttributeList::AT_no_instrument_function: // Interacts with -pg. // Just ignore break; + case AttributeList::AT_no_instrument_function: // Interacts with -pg. + HandleNoInstrumentFunctionAttr(D, Attr, S); + break; case AttributeList::AT_stdcall: case AttributeList::AT_cdecl: case AttributeList::AT_fastcall: @@ -1992,7 +2069,8 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, // Ask target about the attribute. const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); if (!TargetAttrs.ProcessDeclAttribute(scope, D, Attr, S)) - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); + S.Diag(Attr.getLoc(), diag::warn_unknown_attribute_ignored) + << Attr.getName(); break; } } diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 148d146..bd97df2 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -871,6 +871,17 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { // C++ class member Handling //===----------------------------------------------------------------------===// +/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. +Sema::DeclPtrTy +Sema::ActOnAccessSpecifier(AccessSpecifier Access, + SourceLocation ASLoc, SourceLocation ColonLoc) { + assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); + AccessSpecDecl* ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, + ASLoc, ColonLoc); + CurContext->addHiddenDecl(ASDecl); + return DeclPtrTy::make(ASDecl); +} + /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the /// bitfield width if there is one and 'InitExpr' specifies the initializer if @@ -886,10 +897,18 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Expr *Init = static_cast<Expr*>(InitExpr); SourceLocation Loc = D.getIdentifierLoc(); - bool isFunc = D.isFunctionDeclarator(); - + assert(isa<CXXRecordDecl>(CurContext)); assert(!DS.isFriendSpecified()); + bool isFunc = false; + if (D.isFunctionDeclarator()) + isFunc = true; + else if (D.getNumTypeObjects() == 0 && + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename) { + QualType TDType = GetTypeFromParser(DS.getTypeRep()); + isFunc = TDType->isFunctionType(); + } + // C++ 9.2p6: A member shall not be declared to have automatic storage // duration (auto, register) or with the extern storage-class-specifier. // C++ 7.1.1p8: The mutable specifier can be applied only to names of class @@ -911,22 +930,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, // FIXME: It would be nicer if the keyword was ignored only for this // declarator. Otherwise we could get follow-up errors. D.getMutableDeclSpec().ClearStorageClassSpecs(); - } else { - QualType T = GetTypeForDeclarator(D, S); - diag::kind err = static_cast<diag::kind>(0); - if (T->isReferenceType()) - err = diag::err_mutable_reference; - else if (T.isConstQualified()) - err = diag::err_mutable_const; - if (err != 0) { - if (DS.getStorageClassSpecLoc().isValid()) - Diag(DS.getStorageClassSpecLoc(), err); - else - Diag(DS.getThreadSpecLoc(), err); - // FIXME: It would be nicer if the keyword was ignored only for this - // declarator. Otherwise we could get follow-up errors. - D.getMutableDeclSpec().ClearStorageClassSpecs(); - } } break; default: @@ -938,18 +941,6 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, D.getMutableDeclSpec().ClearStorageClassSpecs(); } - if (!isFunc && - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_typename && - D.getNumTypeObjects() == 0) { - // Check also for this case: - // - // typedef int f(); - // f a; - // - QualType TDType = GetTypeFromParser(DS.getTypeRep()); - isFunc = TDType->isFunctionType(); - } - bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified || DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && !isFunc); @@ -1148,6 +1139,7 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, return true; R.clear(); + R.setLookupName(MemberOrBase); } } @@ -1226,18 +1218,25 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, /// containing the field that is being initialized. Returns true if there is an /// uninitialized field was used an updates the SourceLocation parameter; false /// otherwise. -static bool InitExprContainsUninitializedFields(const Stmt* S, - const FieldDecl* LhsField, - SourceLocation* L) { - const MemberExpr* ME = dyn_cast<MemberExpr>(S); - if (ME) { - const NamedDecl* RhsField = ME->getMemberDecl(); +static bool InitExprContainsUninitializedFields(const Stmt *S, + const FieldDecl *LhsField, + SourceLocation *L) { + if (isa<CallExpr>(S)) { + // Do not descend into function calls or constructors, as the use + // of an uninitialized field may be valid. One would have to inspect + // the contents of the function/ctor to determine if it is safe or not. + // i.e. Pass-by-value is never safe, but pass-by-reference and pointers + // may be safe, depending on what the function/ctor does. + return false; + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { + const NamedDecl *RhsField = ME->getMemberDecl(); if (RhsField == LhsField) { // Initializing a field with itself. Throw a warning. // But wait; there are exceptions! // Exception #1: The field may not belong to this record. // e.g. Foo(const Foo& rhs) : A(rhs.A) {} - const Expr* base = ME->getBase(); + const Expr *base = ME->getBase(); if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) { // Even though the field matches, it does not belong to this record. return false; @@ -1248,21 +1247,16 @@ static bool InitExprContainsUninitializedFields(const Stmt* S, return true; } } - bool found = false; - for (Stmt::const_child_iterator it = S->child_begin(); - it != S->child_end() && found == false; - ++it) { - if (isa<CallExpr>(S)) { - // Do not descend into function calls or constructors, as the use - // of an uninitialized field may be valid. One would have to inspect - // the contents of the function/ctor to determine if it is safe or not. - // i.e. Pass-by-value is never safe, but pass-by-reference and pointers - // may be safe, depending on what the function/ctor does. + for (Stmt::const_child_iterator it = S->child_begin(), e = S->child_end(); + it != e; ++it) { + if (!*it) { + // An expression such as 'member(arg ?: "")' may trigger this. continue; } - found = InitExprContainsUninitializedFields(*it, LhsField, L); + if (InitExprContainsUninitializedFields(*it, LhsField, L)) + return true; } - return found; + return false; } Sema::MemInitResult @@ -1375,8 +1369,48 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, for (unsigned i = 0; i < NumArgs; i++) HasDependentArg |= Args[i]->isTypeDependent(); - SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); - if (BaseType->isDependentType() || HasDependentArg) { + SourceLocation BaseLoc + = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); + + if (!BaseType->isDependentType() && !BaseType->isRecordType()) + return Diag(BaseLoc, diag::err_base_init_does_not_name_class) + << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); + + // C++ [class.base.init]p2: + // [...] Unless the mem-initializer-id names a nonstatic data + // member of the constructor’s class or a direct or virtual base + // of that class, the mem-initializer is ill-formed. A + // mem-initializer-list can initialize a base class using any + // name that denotes that base class type. + bool Dependent = BaseType->isDependentType() || HasDependentArg; + + // Check for direct and virtual base classes. + const CXXBaseSpecifier *DirectBaseSpec = 0; + const CXXBaseSpecifier *VirtualBaseSpec = 0; + if (!Dependent) { + FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, + VirtualBaseSpec); + + // C++ [base.class.init]p2: + // Unless the mem-initializer-id names a nonstatic data member of the + // constructor's class or a direct or virtual base of that class, the + // mem-initializer is ill-formed. + if (!DirectBaseSpec && !VirtualBaseSpec) { + // If the class has any dependent bases, then it's possible that + // one of those types will resolve to the same type as + // BaseType. Therefore, just treat this as a dependent base + // class initialization. FIXME: Should we try to check the + // initialization anyway? It seems odd. + if (ClassDecl->hasAnyDependentBases()) + Dependent = true; + else + return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) + << BaseType << Context.getTypeDeclType(ClassDecl) + << BaseTInfo->getTypeLoc().getLocalSourceRange(); + } + } + + if (Dependent) { // Can't check initialization for a base of dependent type or when // any of the arguments are type-dependent expressions. OwningExprResult BaseInit @@ -1396,23 +1430,6 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, BaseInit.takeAs<Expr>(), RParenLoc); } - - if (!BaseType->isRecordType()) - return Diag(BaseLoc, diag::err_base_init_does_not_name_class) - << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); - - // C++ [class.base.init]p2: - // [...] Unless the mem-initializer-id names a nonstatic data - // member of the constructor’s class or a direct or virtual base - // of that class, the mem-initializer is ill-formed. A - // mem-initializer-list can initialize a base class using any - // name that denotes that base class type. - - // Check for direct and virtual base classes. - const CXXBaseSpecifier *DirectBaseSpec = 0; - const CXXBaseSpecifier *VirtualBaseSpec = 0; - FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, - VirtualBaseSpec); // C++ [base.class.init]p2: // If a mem-initializer-id is ambiguous because it designates both @@ -1421,14 +1438,6 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (DirectBaseSpec && VirtualBaseSpec) return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); - // C++ [base.class.init]p2: - // Unless the mem-initializer-id names a nonstatic data membeer of the - // constructor's class ot a direst or virtual base of that class, the - // mem-initializer is ill-formed. - if (!DirectBaseSpec && !VirtualBaseSpec) - return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) - << BaseType << Context.getTypeDeclType(ClassDecl) - << BaseTInfo->getTypeLoc().getLocalSourceRange(); CXXBaseSpecifier *BaseSpec = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); @@ -1571,8 +1580,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, if (Field->isInvalidDecl()) return true; + SourceLocation Loc = Constructor->getLocation(); + if (ImplicitInitKind == IIK_Copy) { - SourceLocation Loc = Constructor->getLocation(); ParmVarDecl *Param = Constructor->getParamDecl(0); QualType ParamType = Param->getType().getNonReferenceType(); @@ -1680,7 +1690,7 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, if (FieldBaseElementType->isRecordType()) { InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); InitializationKind InitKind = - InitializationKind::CreateDefault(Constructor->getLocation()); + InitializationKind::CreateDefault(Loc); InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 0, 0); Sema::OwningExprResult MemberInit = @@ -1692,10 +1702,9 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, CXXMemberInit = new (SemaRef.Context) CXXBaseOrMemberInitializer(SemaRef.Context, - Field, SourceLocation(), - SourceLocation(), + Field, Loc, Loc, MemberInit.takeAs<Expr>(), - SourceLocation()); + Loc); return false; } @@ -1744,38 +1753,67 @@ struct BaseAndFieldInfo { }; } +static void RecordFieldInitializer(BaseAndFieldInfo &Info, + FieldDecl *Top, FieldDecl *Field, + CXXBaseOrMemberInitializer *Init) { + // If the member doesn't need to be initialized, Init will still be null. + if (!Init) + return; + + Info.AllToInit.push_back(Init); + if (Field != Top) { + Init->setMember(Top); + Init->setAnonUnionMember(Field); + } +} + static bool CollectFieldInitializer(BaseAndFieldInfo &Info, FieldDecl *Top, FieldDecl *Field) { - // Overwhelmingly common case: we have a direct initializer for this field. + // Overwhelmingly common case: we have a direct initializer for this field. if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(Field)) { - Info.AllToInit.push_back(Init); - - if (Field != Top) { - Init->setMember(Top); - Init->setAnonUnionMember(Field); - } + RecordFieldInitializer(Info, Top, Field, Init); return false; } if (Info.IIK == IIK_Default && Field->isAnonymousStructOrUnion()) { const RecordType *FieldClassType = Field->getType()->getAs<RecordType>(); assert(FieldClassType && "anonymous struct/union without record type"); - - // Walk through the members, tying in any initializers for fields - // we find. The earlier semantic checks should prevent redundant - // initialization of union members, given the requirement that - // union members never have non-trivial default constructors. - - // TODO: in C++0x, it might be legal to have union members with - // non-trivial default constructors in unions. Revise this - // implementation then with the appropriate semantics. CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(FieldClassType->getDecl()); - for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), - EA = FieldClassDecl->field_end(); FA != EA; FA++) - if (CollectFieldInitializer(Info, Top, *FA)) - return true; + + // Even though union members never have non-trivial default + // constructions in C++03, we still build member initializers for aggregate + // record types which can be union members, and C++0x allows non-trivial + // default constructors for union members, so we ensure that only one + // member is initialized for these. + if (FieldClassDecl->isUnion()) { + // First check for an explicit initializer for one field. + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + EA = FieldClassDecl->field_end(); FA != EA; FA++) { + if (CXXBaseOrMemberInitializer *Init = Info.AllBaseFields.lookup(*FA)) { + RecordFieldInitializer(Info, Top, *FA, Init); + + // Once we've initialized a field of an anonymous union, the union + // field in the class is also initialized, so exit immediately. + return false; + } + } + + // Fallthrough and construct a default initializer for the union as + // a whole, which can call its default constructor if such a thing exists + // (C++0x perhaps). FIXME: It's not clear that this is the correct + // behavior going forward with C++0x, when anonymous unions there are + // finalized, we should revisit this. + } else { + // For structs, we simply descend through to initialize all members where + // necessary. + for (RecordDecl::field_iterator FA = FieldClassDecl->field_begin(), + EA = FieldClassDecl->field_end(); FA != EA; FA++) { + if (CollectFieldInitializer(Info, Top, *FA)) + return true; + } + } } // Don't try to build an implicit initializer if there were semantic @@ -1787,15 +1825,8 @@ static bool CollectFieldInitializer(BaseAndFieldInfo &Info, CXXBaseOrMemberInitializer *Init = 0; if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, Init)) return true; - - // If the member doesn't need to be initialized, Init will still be null. - if (!Init) return false; - Info.AllToInit.push_back(Init); - if (Top != Field) { - Init->setMember(Top); - Init->setAnonUnionMember(Field); - } + RecordFieldInitializer(Info, Top, Field, Init); return false; } @@ -2199,7 +2230,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (FieldClassDecl->hasTrivialDestructor()) continue; - CXXDestructorDecl *Dtor = FieldClassDecl->getDestructor(Context); + CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); CheckDestructorAccess(Field->getLocation(), Dtor, PDiag(diag::err_access_dtor_field) << Field->getDeclName() @@ -2225,7 +2256,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (BaseClassDecl->hasTrivialDestructor()) continue; - CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); // FIXME: caret should be on the start of the class name CheckDestructorAccess(Base->getSourceRange().getBegin(), Dtor, @@ -2252,7 +2283,7 @@ Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, if (BaseClassDecl->hasTrivialDestructor()) continue; - CXXDestructorDecl *Dtor = BaseClassDecl->getDestructor(Context); + CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); CheckDestructorAccess(ClassDecl->getLocation(), Dtor, PDiag(diag::err_access_dtor_vbase) << VBase->getType()); @@ -2326,6 +2357,10 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); + // Keep a set of seen pure methods so we won't diagnose the same method + // more than once. + llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods; + for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), MEnd = FinalOverriders.end(); M != MEnd; @@ -2345,6 +2380,9 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, if (!SO->second.front().Method->isPure()) continue; + if (!SeenPureMethods.insert(SO->second.front().Method)) + continue; + Diag(SO->second.front().Method->getLocation(), diag::note_pure_virtual_function) << SO->second.front().Method->getDeclName(); @@ -2422,12 +2460,12 @@ namespace { /// \brief Perform semantic checks on a class definition that has been /// completing, introducing implicitly-declared members, checking for /// abstract types, etc. -void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { +void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (!Record || Record->isInvalidDecl()) return; if (!Record->isDependentType()) - AddImplicitlyDeclaredMembersToClass(S, Record); + AddImplicitlyDeclaredMembersToClass(Record); if (Record->isInvalidDecl()) return; @@ -2546,268 +2584,101 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, (DeclPtrTy*)FieldCollector->getCurFields(), FieldCollector->getCurNumFields(), LBrac, RBrac, AttrList); - CheckCompletedCXXClass(S, - dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>())); + CheckCompletedCXXClass( + dyn_cast_or_null<CXXRecordDecl>(TagDecl.getAs<Decl>())); +} + +namespace { + /// \brief Helper class that collects exception specifications for + /// implicitly-declared special member functions. + class ImplicitExceptionSpecification { + ASTContext &Context; + bool AllowsAllExceptions; + llvm::SmallPtrSet<CanQualType, 4> ExceptionsSeen; + llvm::SmallVector<QualType, 4> Exceptions; + + public: + explicit ImplicitExceptionSpecification(ASTContext &Context) + : Context(Context), AllowsAllExceptions(false) { } + + /// \brief Whether the special member function should have any + /// exception specification at all. + bool hasExceptionSpecification() const { + return !AllowsAllExceptions; + } + + /// \brief Whether the special member function should have a + /// throw(...) exception specification (a Microsoft extension). + bool hasAnyExceptionSpecification() const { + return false; + } + + /// \brief The number of exceptions in the exception specification. + unsigned size() const { return Exceptions.size(); } + + /// \brief The set of exceptions in the exception specification. + const QualType *data() const { return Exceptions.data(); } + + /// \brief Note that + void CalledDecl(CXXMethodDecl *Method) { + // If we already know that we allow all exceptions, do nothing. + if (AllowsAllExceptions || !Method) + return; + + const FunctionProtoType *Proto + = Method->getType()->getAs<FunctionProtoType>(); + + // If this function can throw any exceptions, make a note of that. + if (!Proto->hasExceptionSpec() || Proto->hasAnyExceptionSpec()) { + AllowsAllExceptions = true; + ExceptionsSeen.clear(); + Exceptions.clear(); + return; + } + + // Record the exceptions in this function's exception specification. + for (FunctionProtoType::exception_iterator E = Proto->exception_begin(), + EEnd = Proto->exception_end(); + E != EEnd; ++E) + if (ExceptionsSeen.insert(Context.getCanonicalType(*E))) + Exceptions.push_back(*E); + } + }; } + /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared /// special functions, such as the default constructor, copy /// constructor, or destructor, to the given C++ class (C++ /// [special]p1). This routine can only be executed just before the /// definition of the class is complete. -/// -/// The scope, if provided, is the class scope. -void Sema::AddImplicitlyDeclaredMembersToClass(Scope *S, - CXXRecordDecl *ClassDecl) { - CanQualType ClassType - = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); - - // FIXME: Implicit declarations have exception specifications, which are - // the union of the specifications of the implicitly called functions. - - if (!ClassDecl->hasUserDeclaredConstructor()) { - // C++ [class.ctor]p5: - // A default constructor for a class X is a constructor of class X - // that can be called without an argument. If there is no - // user-declared constructor for class X, a default constructor is - // implicitly declared. An implicitly-declared default constructor - // is an inline public member of its class. - DeclarationName Name - = Context.DeclarationNames.getCXXConstructorName(ClassType); - CXXConstructorDecl *DefaultCon = - CXXConstructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, - Context.getFunctionType(Context.VoidTy, - 0, 0, false, 0, - /*FIXME*/false, false, - 0, 0, - FunctionType::ExtInfo()), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true); - DefaultCon->setAccess(AS_public); - DefaultCon->setImplicit(); - DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); - if (S) - PushOnScopeChains(DefaultCon, S, true); - else - ClassDecl->addDecl(DefaultCon); - } +void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { + if (!ClassDecl->hasUserDeclaredConstructor()) + ++ASTContext::NumImplicitDefaultConstructors; - if (!ClassDecl->hasUserDeclaredCopyConstructor()) { - // C++ [class.copy]p4: - // If the class definition does not explicitly declare a copy - // constructor, one is declared implicitly. - - // C++ [class.copy]p5: - // The implicitly-declared copy constructor for a class X will - // have the form - // - // X::X(const X&) - // - // if - bool HasConstCopyConstructor = true; - - // -- each direct or virtual base class B of X has a copy - // constructor whose first parameter is of type const B& or - // const volatile B&, and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - HasConstCopyConstructor && Base != ClassDecl->bases_end(); ++Base) { - const CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - HasConstCopyConstructor - = BaseClassDecl->hasConstCopyConstructor(Context); - } - - // -- for all the nonstatic data members of X that are of a - // class type M (or array thereof), each such class type - // has a copy constructor whose first parameter is of type - // const M& or const volatile M&. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(); - HasConstCopyConstructor && Field != ClassDecl->field_end(); - ++Field) { - QualType FieldType = (*Field)->getType(); - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) - FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - const CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - HasConstCopyConstructor - = FieldClassDecl->hasConstCopyConstructor(Context); - } - } - - // Otherwise, the implicitly declared copy constructor will have - // the form - // - // X::X(X&) - QualType ArgType = ClassType; - if (HasConstCopyConstructor) - ArgType = ArgType.withConst(); - ArgType = Context.getLValueReferenceType(ArgType); - - // An implicitly-declared copy constructor is an inline public - // member of its class. - DeclarationName Name - = Context.DeclarationNames.getCXXConstructorName(ClassType); - CXXConstructorDecl *CopyConstructor - = CXXConstructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, - Context.getFunctionType(Context.VoidTy, - &ArgType, 1, - false, 0, - /*FIXME: hasExceptionSpec*/false, - false, 0, 0, - FunctionType::ExtInfo()), - /*TInfo=*/0, - /*isExplicit=*/false, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true); - CopyConstructor->setAccess(AS_public); - CopyConstructor->setImplicit(); - CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); - - // Add the parameter to the constructor. - ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, - ClassDecl->getLocation(), - /*IdentifierInfo=*/0, - ArgType, /*TInfo=*/0, - VarDecl::None, - VarDecl::None, 0); - CopyConstructor->setParams(&FromParam, 1); - if (S) - PushOnScopeChains(CopyConstructor, S, true); - else - ClassDecl->addDecl(CopyConstructor); - } + if (!ClassDecl->hasUserDeclaredCopyConstructor()) + ++ASTContext::NumImplicitCopyConstructors; if (!ClassDecl->hasUserDeclaredCopyAssignment()) { - // Note: The following rules are largely analoguous to the copy - // constructor rules. Note that virtual bases are not taken into account - // for determining the argument type of the operator. Note also that - // operators taking an object instead of a reference are allowed. - // - // C++ [class.copy]p10: - // If the class definition does not explicitly declare a copy - // assignment operator, one is declared implicitly. - // The implicitly-defined copy assignment operator for a class X - // will have the form - // - // X& X::operator=(const X&) - // - // if - bool HasConstCopyAssignment = true; - - // -- each direct base class B of X has a copy assignment operator - // whose parameter is of type const B&, const volatile B& or B, - // and - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - HasConstCopyAssignment && Base != ClassDecl->bases_end(); ++Base) { - assert(!Base->getType()->isDependentType() && - "Cannot generate implicit members for class with dependent bases."); - const CXXRecordDecl *BaseClassDecl - = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - const CXXMethodDecl *MD = 0; - HasConstCopyAssignment = BaseClassDecl->hasConstCopyAssignment(Context, - MD); - } - - // -- for all the nonstatic data members of X that are of a class - // type M (or array thereof), each such class type has a copy - // assignment operator whose parameter is of type const M&, - // const volatile M& or M. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(); - HasConstCopyAssignment && Field != ClassDecl->field_end(); - ++Field) { - QualType FieldType = (*Field)->getType(); - if (const ArrayType *Array = Context.getAsArrayType(FieldType)) - FieldType = Array->getElementType(); - if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { - const CXXRecordDecl *FieldClassDecl - = cast<CXXRecordDecl>(FieldClassType->getDecl()); - const CXXMethodDecl *MD = 0; - HasConstCopyAssignment - = FieldClassDecl->hasConstCopyAssignment(Context, MD); - } - } - - // Otherwise, the implicitly declared copy assignment operator will - // have the form - // - // X& X::operator=(X&) - QualType ArgType = ClassType; - QualType RetType = Context.getLValueReferenceType(ArgType); - if (HasConstCopyAssignment) - ArgType = ArgType.withConst(); - ArgType = Context.getLValueReferenceType(ArgType); - - // An implicitly-declared copy assignment operator is an inline public - // member of its class. - DeclarationName Name = - Context.DeclarationNames.getCXXOperatorName(OO_Equal); - CXXMethodDecl *CopyAssignment = - CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, - Context.getFunctionType(RetType, &ArgType, 1, - false, 0, - /*FIXME: hasExceptionSpec*/false, - false, 0, 0, - FunctionType::ExtInfo()), - /*TInfo=*/0, /*isStatic=*/false, - /*StorageClassAsWritten=*/FunctionDecl::None, - /*isInline=*/true); - CopyAssignment->setAccess(AS_public); - CopyAssignment->setImplicit(); - CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); - CopyAssignment->setCopyAssignment(true); - - // Add the parameter to the operator. - ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, - ClassDecl->getLocation(), - /*Id=*/0, - ArgType, /*TInfo=*/0, - VarDecl::None, - VarDecl::None, 0); - CopyAssignment->setParams(&FromParam, 1); - - // Don't call addedAssignmentOperator. There is no way to distinguish an - // implicit from an explicit assignment operator. - if (S) - PushOnScopeChains(CopyAssignment, S, true); - else - ClassDecl->addDecl(CopyAssignment); - AddOverriddenMethods(ClassDecl, CopyAssignment); + ++ASTContext::NumImplicitCopyAssignmentOperators; + + // If we have a dynamic class, then the copy assignment operator may be + // virtual, so we have to declare it immediately. This ensures that, e.g., + // it shows up in the right place in the vtable and that we diagnose + // problems with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitCopyAssignment(ClassDecl); } if (!ClassDecl->hasUserDeclaredDestructor()) { - // C++ [class.dtor]p2: - // If a class has no user-declared destructor, a destructor is - // declared implicitly. An implicitly-declared destructor is an - // inline public member of its class. - QualType Ty = Context.getFunctionType(Context.VoidTy, - 0, 0, false, 0, - /*FIXME: hasExceptionSpec*/false, - false, 0, 0, FunctionType::ExtInfo()); - - DeclarationName Name - = Context.DeclarationNames.getCXXDestructorName(ClassType); - CXXDestructorDecl *Destructor - = CXXDestructorDecl::Create(Context, ClassDecl, - ClassDecl->getLocation(), Name, Ty, - /*isInline=*/true, - /*isImplicitlyDeclared=*/true); - Destructor->setAccess(AS_public); - Destructor->setImplicit(); - Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); - if (S) - PushOnScopeChains(Destructor, S, true); - else - ClassDecl->addDecl(Destructor); - - // This could be uniqued if it ever proves significant. - Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); + ++ASTContext::NumImplicitDestructors; - AddOverriddenMethods(ClassDecl, Destructor); + // If we have a dynamic class, then the destructor may be virtual, so we + // have to declare the destructor immediately. This ensures that, e.g., it + // shows up in the right place in the vtable and that we diagnose problems + // with the implicit exception specification. + if (ClassDecl->isDynamicClass()) + DeclareImplicitDestructor(ClassDecl); } } @@ -2952,9 +2823,7 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, // Rebuild the function type "R" without any type qualifiers (in // case any of the errors above fired) and with "void" as the - // return type, since constructors don't have return types. We - // *always* have to do this, because GetTypeForDeclarator will - // put in a result type of "int" when none was specified. + // return type, since constructors don't have return types. const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); return Context.getFunctionType(Context.VoidTy, Proto->arg_type_begin(), Proto->getNumArgs(), @@ -2990,8 +2859,11 @@ void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { QualType ClassTy = Context.getTagDeclType(ClassDecl); if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); + const char *ConstRef + = Constructor->getParamDecl(0)->getIdentifier() ? "const &" + : " const &"; Diag(ParamLoc, diag::err_constructor_byvalue_arg) - << FixItHint::CreateInsertion(ParamLoc, " const &"); + << FixItHint::CreateInsertion(ParamLoc, ConstRef); // FIXME: Rather that making the constructor invalid, we should endeavor // to fix the type. @@ -3026,6 +2898,8 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { Context.DeclarationNames.getCXXOperatorName(OO_Delete); if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete)) return true; + + MarkDeclarationReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete); } @@ -3046,7 +2920,7 @@ FTIHasSingleVoidArgument(DeclaratorChunk::FunctionTypeInfo &FTI) { /// emit diagnostics and set the declarator to invalid. Even if this happens, /// will be updated to reflect a well-formed type for the destructor and /// returned. -QualType Sema::CheckDestructorDeclarator(Declarator &D, +QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC) { // C++ [class.dtor]p1: // [...] A typedef-name that names a class is a class-name @@ -3054,11 +2928,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); - if (isa<TypedefType>(DeclaratorType)) { + if (isa<TypedefType>(DeclaratorType)) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) << DeclaratorType; - D.setInvalidType(); - } // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A @@ -3072,9 +2944,10 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, if (!D.isInvalidType()) Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) - << SourceRange(D.getIdentifierLoc()); + << SourceRange(D.getIdentifierLoc()) + << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); + SC = FunctionDecl::None; - D.setInvalidType(); } if (D.getDeclSpec().hasTypeSpecifier() && !D.isInvalidType()) { // Destructors don't have return types, but the parser will @@ -3122,11 +2995,17 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, // Rebuild the function type "R" without any type qualifiers or // parameters (in case any of the errors above fired) and with // "void" as the return type, since destructors don't have return - // types. We *always* have to do this, because GetTypeForDeclarator - // will put in a result type of "int" when none was specified. - // FIXME: Exceptions! + // types. + const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); + if (!Proto) + return QualType(); + return Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, - false, false, 0, 0, FunctionType::ExtInfo()); + Proto->hasExceptionSpec(), + Proto->hasAnyExceptionSpec(), + Proto->getNumExceptions(), + Proto->exception_begin(), + Proto->getExtInfo()); } /// CheckConversionDeclarator - Called by ActOnDeclarator to check the @@ -3434,6 +3313,21 @@ void Sema::ActOnFinishNamespaceDef(DeclPtrTy D, SourceLocation RBrace) { PopDeclContext(); } +/// \brief Retrieve the special "std" namespace, which may require us to +/// implicitly define the namespace. +NamespaceDecl *Sema::getStdNamespace() { + if (!StdNamespace) { + // The "std" namespace has not yet been defined, so build one implicitly. + StdNamespace = NamespaceDecl::Create(Context, + Context.getTranslationUnitDecl(), + SourceLocation(), + &PP.getIdentifierTable().get("std")); + StdNamespace->setImplicit(true); + } + + return StdNamespace; +} + Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -3447,13 +3341,49 @@ Sema::DeclPtrTy Sema::ActOnUsingDirective(Scope *S, assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); UsingDirectiveDecl *UDir = 0; - + NestedNameSpecifier *Qualifier = 0; + if (SS.isSet()) + Qualifier = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + // Lookup namespace name. LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); LookupParsedName(R, S, &SS); if (R.isAmbiguous()) return DeclPtrTy(); + if (R.empty()) { + // Allow "using namespace std;" or "using namespace ::std;" even if + // "std" hasn't been defined yet, for GCC compatibility. + if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && + NamespcName->isStr("std")) { + Diag(IdentLoc, diag::ext_using_undefined_std); + R.addDecl(getStdNamespace()); + R.resolveKind(); + } + // Otherwise, attempt typo correction. + else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, + CTC_NoKeywords, 0)) { + if (R.getAsSingle<NamespaceDecl>() || + R.getAsSingle<NamespaceAliasDecl>()) { + if (DeclContext *DC = computeDeclContext(SS, false)) + Diag(IdentLoc, diag::err_using_directive_member_suggest) + << NamespcName << DC << Corrected << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + else + Diag(IdentLoc, diag::err_using_directive_suggest) + << NamespcName << Corrected + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) + << Corrected; + + NamespcName = Corrected.getAsIdentifierInfo(); + } else { + R.clear(); + R.setLookupName(NamespcName); + } + } + } + if (!R.empty()) { NamedDecl *Named = R.getFoundDecl(); assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) @@ -3566,6 +3496,28 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, return DeclPtrTy::make(UD); } +/// \brief Determine whether a using declaration considers the given +/// declarations as "equivalent", e.g., if they are redeclarations of +/// the same entity or are both typedefs of the same type. +static bool +IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, + bool &SuppressRedeclaration) { + if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) { + SuppressRedeclaration = false; + return true; + } + + if (TypedefDecl *TD1 = dyn_cast<TypedefDecl>(D1)) + if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) { + SuppressRedeclaration = true; + return Context.hasSameType(TD1->getUnderlyingType(), + TD2->getUnderlyingType()); + } + + return false; +} + + /// Determines whether to create a using shadow decl for a particular /// decl, given the set of decls existing prior to this using lookup. bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, @@ -3632,8 +3584,9 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); - if (D->getCanonicalDecl() == Target->getCanonicalDecl()) - return false; + bool Result; + if (IsEquivalentForUsingDecl(Context, D, Target, Result)) + return Result; (isa<TagDecl>(D) ? Tag : NonTag) = D; } @@ -3646,7 +3599,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, FD = cast<FunctionDecl>(Target); NamedDecl *OldDecl = 0; - switch (CheckOverload(FD, Previous, OldDecl)) { + switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) { case Ovl_Overload: return false; @@ -3656,11 +3609,6 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // We found a decl with the exact signature. case Ovl_Match: - if (isa<UsingShadowDecl>(OldDecl)) { - // Silently ignore the possible conflict. - return false; - } - // If we're in a record, we want to hide the target, so we // return true (without a diagnostic) to tell the caller not to // build a shadow decl. @@ -4162,8 +4110,33 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, return DeclPtrTy(); if (R.empty()) { - Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); - return DeclPtrTy(); + if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, + CTC_NoKeywords, 0)) { + if (R.getAsSingle<NamespaceDecl>() || + R.getAsSingle<NamespaceAliasDecl>()) { + if (DeclContext *DC = computeDeclContext(SS, false)) + Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << Corrected << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + else + Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << Corrected + << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); + + Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) + << Corrected; + + Ident = Corrected.getAsIdentifierInfo(); + } else { + R.clear(); + R.setLookupName(Ident); + } + } + + if (R.empty()) { + Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); + return DeclPtrTy(); + } } NamespaceAliasDecl *AliasDecl = @@ -4200,10 +4173,108 @@ namespace { }; } +CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.ctor]p5: + // A default constructor for a class X is a constructor of class X + // that can be called without an argument. If there is no + // user-declared constructor for class X, a default constructor is + // implicitly declared. An implicitly-declared default constructor + // is an inline public member of its class. + assert(!ClassDecl->hasUserDeclaredConstructor() && + "Should not build implicit default constructor!"); + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + + // Direct base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + if (!BaseClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); + else if (CXXConstructorDecl *Constructor + = BaseClassDecl->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + } + + // Virtual base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) { + CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); + if (!BaseClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl(DeclareImplicitDefaultConstructor(BaseClassDecl)); + else if (CXXConstructorDecl *Constructor + = BaseClassDecl->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + } + + // Field destructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); + if (!FieldClassDecl->hasDeclaredDefaultConstructor()) + ExceptSpec.CalledDecl( + DeclareImplicitDefaultConstructor(FieldClassDecl)); + else if (CXXConstructorDecl *Constructor + = FieldClassDecl->getDefaultConstructor()) + ExceptSpec.CalledDecl(Constructor); + } + } + + + // Create the actual constructor declaration. + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName(ClassType); + CXXConstructorDecl *DefaultCon + = CXXConstructorDecl::Create(Context, ClassDecl, + ClassDecl->getLocation(), Name, + Context.getFunctionType(Context.VoidTy, + 0, 0, false, 0, + ExceptSpec.hasExceptionSpecification(), + ExceptSpec.hasAnyExceptionSpecification(), + ExceptSpec.size(), + ExceptSpec.data(), + FunctionType::ExtInfo()), + /*TInfo=*/0, + /*isExplicit=*/false, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + DefaultCon->setAccess(AS_public); + DefaultCon->setImplicit(); + DefaultCon->setTrivial(ClassDecl->hasTrivialConstructor()); + + // Note that we have declared this constructor. + ClassDecl->setDeclaredDefaultConstructor(true); + ++ASTContext::NumImplicitDefaultConstructorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(DefaultCon, S, false); + ClassDecl->addDecl(DefaultCon); + + return DefaultCon; +} + void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor) { assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() && - !Constructor->isUsed()) && + !Constructor->isUsed(false)) && "DefineImplicitDefaultConstructor - call it for implicit default ctor"); CXXRecordDecl *ClassDecl = Constructor->getParent(); @@ -4222,9 +4293,90 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } } +CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { + // C++ [class.dtor]p2: + // If a class has no user-declared destructor, a destructor is + // declared implicitly. An implicitly-declared destructor is an + // inline public member of its class. + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have + // an exception-specification. + ImplicitExceptionSpecification ExceptSpec(Context); + + // Direct base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->bases_begin(), + BEnd = ClassDecl->bases_end(); + B != BEnd; ++B) { + if (B->isVirtual()) // Handled below. + continue; + + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); + } + + // Virtual base-class destructors. + for (CXXRecordDecl::base_class_iterator B = ClassDecl->vbases_begin(), + BEnd = ClassDecl->vbases_end(); + B != BEnd; ++B) { + if (const RecordType *BaseType = B->getType()->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl()))); + } + + // Field destructors. + for (RecordDecl::field_iterator F = ClassDecl->field_begin(), + FEnd = ClassDecl->field_end(); + F != FEnd; ++F) { + if (const RecordType *RecordTy + = Context.getBaseElementType(F->getType())->getAs<RecordType>()) + ExceptSpec.CalledDecl( + LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl()))); + } + + // Create the actual destructor declaration. + QualType Ty = Context.getFunctionType(Context.VoidTy, + 0, 0, false, 0, + ExceptSpec.hasExceptionSpecification(), + ExceptSpec.hasAnyExceptionSpecification(), + ExceptSpec.size(), + ExceptSpec.data(), + FunctionType::ExtInfo()); + + CanQualType ClassType + = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); + DeclarationName Name + = Context.DeclarationNames.getCXXDestructorName(ClassType); + CXXDestructorDecl *Destructor + = CXXDestructorDecl::Create(Context, ClassDecl, + ClassDecl->getLocation(), Name, Ty, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + Destructor->setAccess(AS_public); + Destructor->setImplicit(); + Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); + + // Note that we have declared this destructor. + ClassDecl->setDeclaredDestructor(true); + ++ASTContext::NumImplicitDestructorsDeclared; + + // Introduce this destructor into its scope. + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(Destructor, S, false); + ClassDecl->addDecl(Destructor); + + // This could be uniqued if it ever proves significant. + Destructor->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(Ty)); + + AddOverriddenMethods(ClassDecl, Destructor); + + return Destructor; +} + void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor) { - assert((Destructor->isImplicit() && !Destructor->isUsed()) && + assert((Destructor->isImplicit() && !Destructor->isUsed(false)) && "DefineImplicitDestructor - call it for implicit default dtor"); CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); @@ -4448,12 +4600,197 @@ BuildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, Loc, move(Copy)); } +/// \brief Determine whether the given class has a copy assignment operator +/// that accepts a const-qualified argument. +static bool hasConstCopyAssignment(Sema &S, const CXXRecordDecl *CClass) { + CXXRecordDecl *Class = const_cast<CXXRecordDecl *>(CClass); + + if (!Class->hasDeclaredCopyAssignment()) + S.DeclareImplicitCopyAssignment(Class); + + QualType ClassType = S.Context.getCanonicalType(S.Context.getTypeDeclType(Class)); + DeclarationName OpName + = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); + + DeclContext::lookup_const_iterator Op, OpEnd; + for (llvm::tie(Op, OpEnd) = Class->lookup(OpName); Op != OpEnd; ++Op) { + // C++ [class.copy]p9: + // A user-declared copy assignment operator is a non-static non-template + // member function of class X with exactly one parameter of type X, X&, + // const X&, volatile X& or const volatile X&. + const CXXMethodDecl* Method = dyn_cast<CXXMethodDecl>(*Op); + if (!Method) + continue; + + if (Method->isStatic()) + continue; + if (Method->getPrimaryTemplate()) + continue; + const FunctionProtoType *FnType = + Method->getType()->getAs<FunctionProtoType>(); + assert(FnType && "Overloaded operator has no prototype."); + // Don't assert on this; an invalid decl might have been left in the AST. + if (FnType->getNumArgs() != 1 || FnType->isVariadic()) + continue; + bool AcceptsConst = true; + QualType ArgType = FnType->getArgType(0); + if (const LValueReferenceType *Ref = ArgType->getAs<LValueReferenceType>()){ + ArgType = Ref->getPointeeType(); + // Is it a non-const lvalue reference? + if (!ArgType.isConstQualified()) + AcceptsConst = false; + } + if (!S.Context.hasSameUnqualifiedType(ArgType, ClassType)) + continue; + + // We have a single argument of type cv X or cv X&, i.e. we've found the + // copy assignment operator. Return whether it accepts const arguments. + return AcceptsConst; + } + assert(Class->isInvalidDecl() && + "No copy assignment operator declared in valid code."); + return false; +} + +CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { + // Note: The following rules are largely analoguous to the copy + // constructor rules. Note that virtual bases are not taken into account + // for determining the argument type of the operator. Note also that + // operators taking an object instead of a reference are allowed. + + + // C++ [class.copy]p10: + // If the class definition does not explicitly declare a copy + // assignment operator, one is declared implicitly. + // The implicitly-defined copy assignment operator for a class X + // will have the form + // + // X& X::operator=(const X&) + // + // if + bool HasConstCopyAssignment = true; + + // -- each direct base class B of X has a copy assignment operator + // whose parameter is of type const B&, const volatile B& or B, + // and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyAssignment && Base != BaseEnd; ++Base) { + assert(!Base->getType()->isDependentType() && + "Cannot generate implicit members for class with dependent bases."); + const CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + HasConstCopyAssignment = hasConstCopyAssignment(*this, BaseClassDecl); + } + + // -- for all the nonstatic data members of X that are of a class + // type M (or array thereof), each such class type has a copy + // assignment operator whose parameter is of type const M&, + // const volatile M& or M. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyAssignment && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + const CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + HasConstCopyAssignment = hasConstCopyAssignment(*this, FieldClassDecl); + } + } + + // Otherwise, the implicitly declared copy assignment operator will + // have the form + // + // X& X::operator=(X&) + QualType ArgType = Context.getTypeDeclType(ClassDecl); + QualType RetType = Context.getLValueReferenceType(ArgType); + if (HasConstCopyAssignment) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + if (!BaseClassDecl->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(BaseClassDecl); + + if (CXXMethodDecl *CopyAssign + = BaseClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment)) + ExceptSpec.CalledDecl(CopyAssign); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + + if (!FieldClassDecl->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(FieldClassDecl); + + if (CXXMethodDecl *CopyAssign + = FieldClassDecl->getCopyAssignmentOperator(HasConstCopyAssignment)) + ExceptSpec.CalledDecl(CopyAssign); + } + } + + // An implicitly-declared copy assignment operator is an inline public + // member of its class. + DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); + CXXMethodDecl *CopyAssignment + = CXXMethodDecl::Create(Context, ClassDecl, ClassDecl->getLocation(), Name, + Context.getFunctionType(RetType, &ArgType, 1, + false, 0, + ExceptSpec.hasExceptionSpecification(), + ExceptSpec.hasAnyExceptionSpecification(), + ExceptSpec.size(), + ExceptSpec.data(), + FunctionType::ExtInfo()), + /*TInfo=*/0, /*isStatic=*/false, + /*StorageClassAsWritten=*/FunctionDecl::None, + /*isInline=*/true); + CopyAssignment->setAccess(AS_public); + CopyAssignment->setImplicit(); + CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment()); + CopyAssignment->setCopyAssignment(true); + + // Add the parameter to the operator. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, + ClassDecl->getLocation(), + /*Id=*/0, + ArgType, /*TInfo=*/0, + VarDecl::None, + VarDecl::None, 0); + CopyAssignment->setParams(&FromParam, 1); + + // Note that we have added this copy-assignment operator. + ClassDecl->setDeclaredCopyAssignment(true); + ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; + + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyAssignment, S, false); + ClassDecl->addDecl(CopyAssignment); + + AddOverriddenMethods(ClassDecl, CopyAssignment); + return CopyAssignment; +} + void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *CopyAssignOperator) { assert((CopyAssignOperator->isImplicit() && CopyAssignOperator->isOverloadedOperator() && CopyAssignOperator->getOverloadedOperator() == OO_Equal && - !CopyAssignOperator->isUsed()) && + !CopyAssignOperator->isUsed(false)) && "DefineImplicitCopyAssignment called for wrong function"); CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); @@ -4554,6 +4891,8 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // \brief Reference to the __builtin_memcpy function. Expr *BuiltinMemCpyRef = 0; + // \brief Reference to the __builtin_objc_memmove_collectable function. + Expr *CollectableMemCpyRef = 0; // Assign non-static members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), @@ -4630,9 +4969,35 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, // Take the address of the field references for "from" and "to". From = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(From)); To = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(To)); - + + bool NeedsCollectableMemCpy = + (BaseType->isRecordType() && + BaseType->getAs<RecordType>()->getDecl()->hasObjectMember()); + + if (NeedsCollectableMemCpy) { + if (!CollectableMemCpyRef) { + // Create a reference to the __builtin_objc_memmove_collectable function. + LookupResult R(*this, + &Context.Idents.get("__builtin_objc_memmove_collectable"), + Loc, LookupOrdinaryName); + LookupName(R, TUScope, true); + + FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>(); + if (!CollectableMemCpy) { + // Something went horribly wrong earlier, and we will have + // complained about it. + Invalid = true; + continue; + } + + CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, + CollectableMemCpy->getType(), + Loc, 0).takeAs<Expr>(); + assert(CollectableMemCpyRef && "Builtin reference cannot fail"); + } + } // Create a reference to the __builtin_memcpy builtin function. - if (!BuiltinMemCpyRef) { + else if (!BuiltinMemCpyRef) { LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc, LookupOrdinaryName); LookupName(R, TUScope, true); @@ -4658,10 +5023,18 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, llvm::SmallVector<SourceLocation, 4> Commas; // FIXME: Silly Commas.push_back(Loc); Commas.push_back(Loc); - OwningExprResult Call = ActOnCallExpr(/*Scope=*/0, - Owned(BuiltinMemCpyRef->Retain()), - Loc, move_arg(CallArgs), - Commas.data(), Loc); + OwningExprResult Call = ExprError(); + if (NeedsCollectableMemCpy) + Call = ActOnCallExpr(/*Scope=*/0, + Owned(CollectableMemCpyRef->Retain()), + Loc, move_arg(CallArgs), + Commas.data(), Loc); + else + Call = ActOnCallExpr(/*Scope=*/0, + Owned(BuiltinMemCpyRef->Retain()), + Loc, move_arg(CallArgs), + Commas.data(), Loc); + assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); Statements.push_back(Call.takeAs<Expr>()); continue; @@ -4712,12 +5085,185 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setBody(Body.takeAs<Stmt>()); } +CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( + CXXRecordDecl *ClassDecl) { + // C++ [class.copy]p4: + // If the class definition does not explicitly declare a copy + // constructor, one is declared implicitly. + + // C++ [class.copy]p5: + // The implicitly-declared copy constructor for a class X will + // have the form + // + // X::X(const X&) + // + // if + bool HasConstCopyConstructor = true; + + // -- each direct or virtual base class B of X has a copy + // constructor whose first parameter is of type const B& or + // const volatile B&, and + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(BaseClassDecl); + + HasConstCopyConstructor + = BaseClassDecl->hasConstCopyConstructor(Context); + } + + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + HasConstCopyConstructor && Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(BaseClassDecl); + + HasConstCopyConstructor + = BaseClassDecl->hasConstCopyConstructor(Context); + } + + // -- for all the nonstatic data members of X that are of a + // class type M (or array thereof), each such class type + // has a copy constructor whose first parameter is of type + // const M& or const volatile M&. + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + HasConstCopyConstructor && Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + if (!FieldClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(FieldClassDecl); + + HasConstCopyConstructor + = FieldClassDecl->hasConstCopyConstructor(Context); + } + } + + // Otherwise, the implicitly declared copy constructor will have + // the form + // + // X::X(X&) + QualType ClassType = Context.getTypeDeclType(ClassDecl); + QualType ArgType = ClassType; + if (HasConstCopyConstructor) + ArgType = ArgType.withConst(); + ArgType = Context.getLValueReferenceType(ArgType); + + // C++ [except.spec]p14: + // An implicitly declared special member function (Clause 12) shall have an + // exception-specification. [...] + ImplicitExceptionSpecification ExceptSpec(Context); + unsigned Quals = HasConstCopyConstructor? Qualifiers::Const : 0; + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + BaseEnd = ClassDecl->bases_end(); + Base != BaseEnd; + ++Base) { + // Virtual bases are handled below. + if (Base->isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(BaseClassDecl); + + if (CXXConstructorDecl *CopyConstructor + = BaseClassDecl->getCopyConstructor(Context, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), + BaseEnd = ClassDecl->vbases_end(); + Base != BaseEnd; + ++Base) { + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(BaseClassDecl); + + if (CXXConstructorDecl *CopyConstructor + = BaseClassDecl->getCopyConstructor(Context, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; + ++Field) { + QualType FieldType = Context.getBaseElementType((*Field)->getType()); + if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { + CXXRecordDecl *FieldClassDecl + = cast<CXXRecordDecl>(FieldClassType->getDecl()); + if (!FieldClassDecl->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(FieldClassDecl); + + if (CXXConstructorDecl *CopyConstructor + = FieldClassDecl->getCopyConstructor(Context, Quals)) + ExceptSpec.CalledDecl(CopyConstructor); + } + } + + // An implicitly-declared copy constructor is an inline public + // member of its class. + DeclarationName Name + = Context.DeclarationNames.getCXXConstructorName( + Context.getCanonicalType(ClassType)); + CXXConstructorDecl *CopyConstructor + = CXXConstructorDecl::Create(Context, ClassDecl, + ClassDecl->getLocation(), Name, + Context.getFunctionType(Context.VoidTy, + &ArgType, 1, + false, 0, + ExceptSpec.hasExceptionSpecification(), + ExceptSpec.hasAnyExceptionSpecification(), + ExceptSpec.size(), + ExceptSpec.data(), + FunctionType::ExtInfo()), + /*TInfo=*/0, + /*isExplicit=*/false, + /*isInline=*/true, + /*isImplicitlyDeclared=*/true); + CopyConstructor->setAccess(AS_public); + CopyConstructor->setImplicit(); + CopyConstructor->setTrivial(ClassDecl->hasTrivialCopyConstructor()); + + // Note that we have declared this constructor. + ClassDecl->setDeclaredCopyConstructor(true); + ++ASTContext::NumImplicitCopyConstructorsDeclared; + + // Add the parameter to the constructor. + ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, + ClassDecl->getLocation(), + /*IdentifierInfo=*/0, + ArgType, /*TInfo=*/0, + VarDecl::None, + VarDecl::None, 0); + CopyConstructor->setParams(&FromParam, 1); + if (Scope *S = getScopeForContext(ClassDecl)) + PushOnScopeChains(CopyConstructor, S, false); + ClassDecl->addDecl(CopyConstructor); + + return CopyConstructor; +} + void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *CopyConstructor, unsigned TypeQuals) { assert((CopyConstructor->isImplicit() && CopyConstructor->isCopyConstructor(TypeQuals) && - !CopyConstructor->isUsed()) && + !CopyConstructor->isUsed(false)) && "DefineImplicitCopyConstructor - call it for implicit copy ctor"); CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); @@ -4810,7 +5356,7 @@ void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); if (!ClassDecl->isInvalidDecl() && !VD->isInvalidDecl() && !ClassDecl->hasTrivialDestructor() && !ClassDecl->isDependentContext()) { - CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context); + CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); MarkDeclarationReferenced(VD->getLocation(), Destructor); CheckDestructorAccess(VD->getLocation(), Destructor, PDiag(diag::err_access_dtor_var) @@ -5477,8 +6023,8 @@ VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType, /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch /// handler. Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { - TypeSourceInfo *TInfo = 0; - QualType ExDeclType = GetTypeForDeclarator(D, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType ExDeclType = TInfo->getType(); bool Invalid = D.isInvalidType(); IdentifierInfo *II = D.getIdentifier(); @@ -5632,14 +6178,11 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, // friend templates because ActOnTag never produces a ClassTemplateDecl // for a TUK_Friend. Declarator TheDeclarator(DS, Declarator::MemberContext); - TypeSourceInfo *TSI; - QualType T = GetTypeForDeclarator(TheDeclarator, S, &TSI); + TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); + QualType T = TSI->getType(); if (TheDeclarator.isInvalidType()) return DeclPtrTy(); - if (!TSI) - TSI = Context.getTrivialTypeSourceInfo(T, DS.getSourceRange().getBegin()); - // This is definitely an error in C++98. It's probably meant to // be forbidden in C++0x, too, but the specification is just // poorly written. @@ -5701,8 +6244,8 @@ Sema::ActOnFriendFunctionDecl(Scope *S, assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); SourceLocation Loc = D.getIdentifierLoc(); - TypeSourceInfo *TInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); // C++ [class.friend]p1 // A friend of a class is a function or class.... @@ -5759,13 +6302,18 @@ Sema::ActOnFriendFunctionDecl(Scope *S, LookupQualifiedName(Previous, DC); - // If searching in that context implicitly found a declaration in - // a different context, treat it like it wasn't found at all. + // Ignore things found implicitly in the wrong scope. // TODO: better diagnostics for this case. Suggesting the right // qualified scope would be nice... - // FIXME: getRepresentativeDecl() is not right here at all - if (Previous.empty() || - !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) { + LookupResult::Filter F = Previous.makeFilter(); + while (F.hasNext()) { + NamedDecl *D = F.next(); + if (!D->getDeclContext()->getLookupContext()->Equals(DC)) + F.erase(); + } + F.done(); + + if (Previous.empty()) { D.setInvalidType(); Diag(Loc, diag::err_qualified_friend_not_found) << Name << T; return DeclPtrTy(); @@ -6061,9 +6609,9 @@ Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && "Parser allowed 'typedef' as storage class of condition decl."); - TypeSourceInfo *TInfo = 0; TagDecl *OwnedTag = 0; - QualType Ty = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag); + QualType Ty = TInfo->getType(); if (Ty->isFunctionType()) { // The declarator shall not specify a function... // We exit without creating a CXXConditionDeclExpr because a FunctionDecl @@ -6127,7 +6675,7 @@ bool Sema::DefineUsedVTables() { if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(DynamicClasses[I])) { const FunctionDecl *Definition = 0; - if (KeyFunction->getBody(Definition)) + if (KeyFunction->hasBody(Definition)) MarkVTableUsed(Definition->getLocation(), DynamicClasses[I], true); } } @@ -6150,7 +6698,7 @@ bool Sema::DefineUsedVTables() { // defined in another translation unit, we don't need to emit the // vtable even though we're using it. const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class); - if (KeyFunction && !KeyFunction->getBody()) { + if (KeyFunction && !KeyFunction->hasBody()) { switch (KeyFunction->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: @@ -6198,7 +6746,7 @@ bool Sema::DefineUsedVTables() { // Optionally warn if we're emitting a weak vtable. if (Class->getLinkage() == ExternalLinkage && Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) { - if (!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) + if (!KeyFunction || (KeyFunction->hasBody() && KeyFunction->isInlined())) Diag(Class->getLocation(), diag::warn_weak_vtable) << Class; } } @@ -6279,8 +6827,7 @@ void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { = Context.getBaseElementType(Field->getType()) ->getAs<RecordType>()) { CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); - if (CXXDestructorDecl *Destructor - = const_cast<CXXDestructorDecl*>(RD->getDestructor(Context))) { + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { MarkDeclarationReferenced(Field->getLocation(), Destructor); CheckDestructorAccess(Field->getLocation(), Destructor, PDiag(diag::err_access_dtor_ivar) diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 3b05f5a..21aeb59 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -414,7 +414,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc) { - ObjCCategoryDecl *CDecl = 0; + ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); /// Check that class of this category is already completely declared. @@ -429,28 +429,21 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, return DeclPtrTy::make(CDecl); } - if (!CategoryName) { - // Class extensions require a special treatment. Use an existing one. - // Note that 'getClassExtension()' can return NULL. - CDecl = IDecl->getClassExtension(); - if (IDecl->getImplementation()) { - Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; - Diag(IDecl->getImplementation()->getLocation(), - diag::note_implementation_declared); - } + if (!CategoryName && IDecl->getImplementation()) { + Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; + Diag(IDecl->getImplementation()->getLocation(), + diag::note_implementation_declared); } - if (!CDecl) { - CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, - ClassLoc, CategoryLoc, CategoryName); - // FIXME: PushOnScopeChains? - CurContext->addDecl(CDecl); + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, + ClassLoc, CategoryLoc, CategoryName); + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); - CDecl->setClassInterface(IDecl); - // Insert first use of class extension to the list of class's categories. - if (!CategoryName) - CDecl->insertNextClassCategory(); - } + CDecl->setClassInterface(IDecl); + // Insert class extension to the list of class's categories. + if (!CategoryName) + CDecl->insertNextClassCategory(); // If the interface is deprecated, warn about it. (void)DiagnoseUseOfDecl(IDecl, ClassLoc); @@ -969,13 +962,11 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl, CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, InsMap, ClsMap, I); // Check class extensions (unnamed categories) - for (ObjCCategoryDecl *Categories = I->getCategoryList(); - Categories; Categories = Categories->getNextClassCategory()) { - if (Categories->IsClassExtension()) { - ImplMethodsVsClassMethods(S, IMPDecl, Categories, IncompleteImpl); - break; - } - } + for (const ObjCCategoryDecl *Categories = I->getFirstClassExtension(); + Categories; Categories = Categories->getNextClassExtension()) + ImplMethodsVsClassMethods(S, IMPDecl, + const_cast<ObjCCategoryDecl*>(Categories), + IncompleteImpl); } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. @@ -1775,9 +1766,9 @@ Sema::DeclPtrTy Sema::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { if (getLangOptions().CPlusPlus) CheckExtraCXXDefaultArguments(D); - TypeSourceInfo *TInfo = 0; TagDecl *OwnedDecl = 0; - QualType ExceptionType = GetTypeForDeclarator(D, S, &TInfo, &OwnedDecl); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedDecl); + QualType ExceptionType = TInfo->getType(); if (getLangOptions().CPlusPlus && OwnedDecl && OwnedDecl->isDefinition()) { // Objective-C++: Types shall not be defined in exception types. @@ -1821,7 +1812,8 @@ void Sema::CollectIvarsToConstructOrDestruct(const ObjCInterfaceDecl *OI, } // Find ivars to construct/destruct in class extension. - if (const ObjCCategoryDecl *CDecl = OI->getClassExtension()) { + for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; + CDecl = CDecl->getNextClassExtension()) { for (ObjCCategoryDecl::ivar_iterator I = CDecl->ivar_begin(), E = CDecl->ivar_end(); I != E; ++I) { ObjCIvarDecl *Iv = (*I); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp index 7d73fe4..34a479a 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExceptionSpec.cpp @@ -249,6 +249,10 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, SourceLocation NewLoc, bool *MissingExceptionSpecification, bool *MissingEmptyExceptionSpecification) { + // Just completely ignore this under -fno-exceptions. + if (!getLangOptions().Exceptions) + return false; + if (MissingExceptionSpecification) *MissingExceptionSpecification = false; @@ -318,6 +322,11 @@ bool Sema::CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Superset, SourceLocation SuperLoc, const FunctionProtoType *Subset, SourceLocation SubLoc) { + + // Just auto-succeed under -fno-exceptions. + if (!getLangOptions().Exceptions) + return false; + // FIXME: As usual, we could be more specific in our error messages, but // that better waits until we've got types with source locations. diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp index f745352..5f46a97 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExpr.cpp @@ -164,7 +164,7 @@ void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, if (!sentinelExpr) return; if (sentinelExpr->isTypeDependent()) return; if (sentinelExpr->isValueDependent()) return; - if (sentinelExpr->getType()->isPointerType() && + if (sentinelExpr->getType()->isAnyPointerType() && sentinelExpr->IgnoreParenCasts()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) return; @@ -388,7 +388,7 @@ Sema::ActOnStringLiteral(const Token *StringToks, unsigned NumStringToks) { if (Literal.Pascal) StrTy = Context.UnsignedCharTy; // A C++ string literal has a const-qualified element type (C++ 2.13.4p1). - if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings ) + if (getLangOptions().CPlusPlus || getLangOptions().ConstStrings) StrTy.addConst(); // Get an array type for the string, according to C99 6.4.5. This includes @@ -475,6 +475,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, SourceLocation Loc, if (isa<NonTypeTemplateParmDecl>(VD)) { // Non-type template parameters can be referenced anywhere they are // visible. + Ty = Ty.getNonLValueExprType(Context); } else if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { if (const FunctionDecl *FD = MD->getParent()->isLocalClass()) { if (VD->hasLocalStorage() && VD->getDeclContext() != CurContext) { @@ -677,26 +678,6 @@ static void DecomposeUnqualifiedId(Sema &SemaRef, } } -/// Decompose the given template name into a list of lookup results. -/// -/// The unqualified ID must name a non-dependent template, which can -/// be more easily tested by checking whether DecomposeUnqualifiedId -/// found template arguments. -static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) { - assert(Id.getKind() == UnqualifiedId::IK_TemplateId); - TemplateName TName = - Sema::TemplateTy::make(Id.TemplateId->Template).getAsVal<TemplateName>(); - - if (TemplateDecl *TD = TName.getAsTemplateDecl()) - R.addDecl(TD); - else if (OverloadedTemplateStorage *OT = TName.getAsOverloadedTemplate()) - for (OverloadedTemplateStorage::iterator I = OT->begin(), E = OT->end(); - I != E; ++I) - R.addDecl(*I); - - R.resolveKind(); -} - /// Determines whether the given record is "fully-formed" at the given /// location, i.e. whether a qualified lookup into it is assured of /// getting consistent results already. @@ -889,8 +870,8 @@ static void DiagnoseInstanceReference(Sema &SemaRef, /// Diagnose an empty lookup. /// /// \return false if new lookup candidates were found -bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, - LookupResult &R, CorrectTypoContext CTC) { +bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, + CorrectTypoContext CTC) { DeclarationName Name = R.getLookupName(); unsigned diagnostic = diag::err_undeclared_var_use; @@ -906,7 +887,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // unqualified lookup. This is useful when (for example) the // original lookup would not have found something because it was a // dependent name. - for (DeclContext *DC = SS.isEmpty()? CurContext : 0; + for (DeclContext *DC = SS.isEmpty() ? CurContext : 0; DC; DC = DC->getParent()) { if (isa<CXXRecordDecl>(DC)) { LookupQualifiedName(R, DC); @@ -923,11 +904,29 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // Give a code modification hint to insert 'this->'. // TODO: fixit for inserting 'Base<T>::' in the other cases. // Actually quite difficult! - if (isInstance) + if (isInstance) { Diag(R.getNameLoc(), diagnostic) << Name << FixItHint::CreateInsertion(R.getNameLoc(), "this->"); - else + + UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>( + CallsUndergoingInstantiation.back()->getCallee()); + CXXMethodDecl *DepMethod = cast<CXXMethodDecl>( + CurMethod->getInstantiatedFromMemberFunction()); + QualType DepThisType = DepMethod->getThisType(Context); + CXXThisExpr *DepThis = new (Context) CXXThisExpr(R.getNameLoc(), + DepThisType, false); + TemplateArgumentListInfo TList; + if (ULE->hasExplicitTemplateArgs()) + ULE->copyTemplateArgumentsInto(TList); + CXXDependentScopeMemberExpr *DepExpr = + CXXDependentScopeMemberExpr::Create( + Context, DepThis, DepThisType, true, SourceLocation(), + ULE->getQualifier(), ULE->getQualifierRange(), NULL, Name, + R.getNameLoc(), &TList); + CallsUndergoingInstantiation.back()->setCallee(DepExpr); + } else { Diag(R.getNameLoc(), diagnostic) << Name; + } // Do we really want to note all of these? for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) @@ -941,7 +940,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, // We didn't find anything, so try to correct for a typo. DeclarationName Corrected; - if (S && (Corrected = CorrectTypo(R, S, &SS, false, CTC))) { + if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) { if (!R.empty()) { if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) { if (SS.isEmpty()) @@ -1746,8 +1745,29 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, // Variable will be bound by-copy, make it const within the closure. ExprTy.addConst(); - return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, false, - constAdded)); + QualType T = VD->getType(); + BlockDeclRefExpr *BDRE = new (Context) BlockDeclRefExpr(VD, + ExprTy, Loc, false, + constAdded); + if (getLangOptions().CPlusPlus) { + if (!T->isDependentType() && !T->isReferenceType()) { + Expr *E = new (Context) + DeclRefExpr(const_cast<ValueDecl*>(BDRE->getDecl()), T, + SourceLocation()); + + OwningExprResult Res = PerformCopyInitialization( + InitializedEntity::InitializeBlock(VD->getLocation(), + T, false), + SourceLocation(), + Owned(E)); + if (!Res.isInvalid()) { + Res = MaybeCreateCXXExprWithTemporaries(move(Res)); + Expr *Init = Res.takeAs<Expr>(); + BDRE->setCopyConstructorExpr(Init); + } + } + } + return Owned(BDRE); } // If this reference is not in a block or if the referenced variable is // within the block, create a normal DeclRefExpr. @@ -2560,13 +2580,23 @@ bool Sema::CheckQualifiedMemberReference(Expr *BaseExpr, static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, SourceRange BaseRange, const RecordType *RTy, - SourceLocation OpLoc, CXXScopeSpec &SS) { + SourceLocation OpLoc, CXXScopeSpec &SS, + bool HasTemplateArgs) { RecordDecl *RDecl = RTy->getDecl(); if (SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), SemaRef.PDiag(diag::err_typecheck_incomplete_tag) << BaseRange)) return true; + if (HasTemplateArgs) { + // LookupTemplateName doesn't expect these both to exist simultaneously. + QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); + + bool MOUS; + SemaRef.LookupTemplateName(R, 0, SS, ObjectType, false, MOUS); + return false; + } + DeclContext *DC = RDecl; if (SS.isSet()) { // If the member name was a qualified-id, look into the @@ -2610,6 +2640,7 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, return false; } else { R.clear(); + R.setLookupName(Name); } return false; @@ -2640,14 +2671,14 @@ Sema::BuildMemberReferenceExpr(ExprArg BaseArg, QualType BaseType, if (IsArrow) RecordTy = RecordTy->getAs<PointerType>()->getPointeeType(); if (LookupMemberExprInRecord(*this, R, SourceRange(), RecordTy->getAs<RecordType>(), - OpLoc, SS)) + OpLoc, SS, TemplateArgs != 0)) return ExprError(); // Explicit member accesses. } else { OwningExprResult Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, - SS, /*ObjCImpDecl*/ DeclPtrTy()); + SS, /*ObjCImpDecl*/ DeclPtrTy(), TemplateArgs != 0); if (Result.isInvalid()) { Owned(Base); @@ -2860,7 +2891,7 @@ Sema::OwningExprResult Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, - DeclPtrTy ObjCImpDecl) { + DeclPtrTy ObjCImpDecl, bool HasTemplateArgs) { assert(BaseExpr && "no base expression"); // Perform default conversions. @@ -2893,6 +2924,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, OwningExprResult NewBase = ActOnCallExpr(0, ExprArg(*this, BaseExpr), Loc, MultiExprArg(*this, 0, 0), 0, Loc); + BaseExpr = 0; if (NewBase.isInvalid()) return ExprError(); @@ -2973,7 +3005,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, QualType PType; if (Getter) - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); else // Get the expression type from Setter's incoming parameter. PType = (*(Setter->param_end() -1))->getType(); @@ -3037,7 +3069,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, // Handle field access to simple records. if (const RecordType *RTy = BaseType->getAs<RecordType>()) { if (LookupMemberExprInRecord(*this, R, BaseExpr->getSourceRange(), - RTy, OpLoc, SS)) + RTy, OpLoc, SS, HasTemplateArgs)) return ExprError(); return Owned((Expr*) 0); } @@ -3069,6 +3101,9 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, IV->getNameAsString()); Diag(IV->getLocation(), diag::note_previous_decl) << IV->getDeclName(); + } else { + Res.clear(); + Res.setLookupName(Member); } } @@ -3146,7 +3181,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, return ExprError(); return Owned(ObjCMessageExpr::Create(Context, - OMD->getResultType().getNonReferenceType(), + OMD->getSendResultType(), OpLoc, BaseExpr, Sel, OMD, NULL, 0, MemberLoc)); } @@ -3239,44 +3274,24 @@ Sema::OwningExprResult Sema::ActOnMemberAccessExpr(Scope *S, ExprArg BaseArg, TemplateArgs); } else { LookupResult R(*this, Name, NameLoc, LookupMemberName); - if (TemplateArgs) { - // Re-use the lookup done for the template name. - DecomposeTemplateName(R, Id); - - // Re-derive the naming class. - if (SS.isSet()) { - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - if (const Type *Ty = Qualifier->getAsType()) - if (CXXRecordDecl *NamingClass = Ty->getAsCXXRecordDecl()) - R.setNamingClass(NamingClass); - } else { - QualType BaseType = Base->getType(); - if (const PointerType *Ptr = BaseType->getAs<PointerType>()) - BaseType = Ptr->getPointeeType(); - if (CXXRecordDecl *NamingClass = BaseType->getAsCXXRecordDecl()) - R.setNamingClass(NamingClass); - } - } else { - Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, - SS, ObjCImpDecl); + Result = LookupMemberExpr(R, Base, IsArrow, OpLoc, + SS, ObjCImpDecl, TemplateArgs != 0); - if (Result.isInvalid()) { - Owned(Base); - return ExprError(); - } + if (Result.isInvalid()) { + Owned(Base); + return ExprError(); + } - if (Result.get()) { - // The only way a reference to a destructor can be used is to - // immediately call it, which falls into this case. If the - // next token is not a '(', produce a diagnostic and build the - // call now. - if (!HasTrailingLParen && - Id.getKind() == UnqualifiedId::IK_DestructorName) - return DiagnoseDtorReference(NameLoc, move(Result)); + if (Result.get()) { + // The only way a reference to a destructor can be used is to + // immediately call it, which falls into this case. If the + // next token is not a '(', produce a diagnostic and build the + // call now. + if (!HasTrailingLParen && + Id.getKind() == UnqualifiedId::IK_DestructorName) + return DiagnoseDtorReference(NameLoc, move(Result)); - return move(Result); - } + return move(Result); } Result = BuildMemberReferenceExpr(ExprArg(*this, Base), Base->getType(), @@ -3304,9 +3319,10 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true); - InstantiatingTemplate Inst(*this, CallLoc, Param, - ArgList.getInnermost().getFlatArgumentList(), - ArgList.getInnermost().flat_size()); + std::pair<const TemplateArgument *, unsigned> Innermost + = ArgList.getInnermost(); + InstantiatingTemplate Inst(*this, CallLoc, Param, Innermost.first, + Innermost.second); OwningExprResult Result = SubstExpr(UninstExpr, ArgList); if (Result.isInvalid()) @@ -3560,7 +3576,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, BO->getOpcode() == BinaryOperator::PtrMemI) { if (const FunctionProtoType *FPT = BO->getType()->getAs<FunctionProtoType>()) { - QualType ResultTy = FPT->getResultType().getNonReferenceType(); + QualType ResultTy = FPT->getCallResultType(Context); ExprOwningPtr<CXXMemberCallExpr> TheCall(this, new (Context) CXXMemberCallExpr(Context, BO, Args, @@ -3650,7 +3666,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, return ExprError(); // We know the result type of the call, set it. - TheCall->setType(FuncT->getResultType().getNonReferenceType()); + TheCall->setType(FuncT->getCallResultType(Context)); if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FuncT)) { if (ConvertArgumentsForCall(&*TheCall, Fn, FDecl, Proto, Args, NumArgs, @@ -3663,7 +3679,7 @@ Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, // Check if we have too few/too many template arguments, based // on our knowledge of the function definition. const FunctionDecl *Def = 0; - if (FDecl->getBody(Def) && NumArgs != Def->param_size()) { + if (FDecl->hasBody(Def) && NumArgs != Def->param_size()) { const FunctionProtoType *Proto = Def->getType()->getAs<FunctionProtoType>(); if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) { @@ -3893,12 +3909,13 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, if (!castType->isArithmeticType()) { QualType castExprType = castExpr->getType(); - if (!castExprType->isIntegralType() && castExprType->isArithmeticType()) + if (!castExprType->isIntegralType(Context) && + castExprType->isArithmeticType()) return Diag(castExpr->getLocStart(), diag::err_cast_pointer_from_non_pointer_int) << castExprType << castExpr->getSourceRange(); } else if (!castExpr->getType()->isArithmeticType()) { - if (!castType->isIntegralType() && castType->isArithmeticType()) + if (!castType->isIntegralType(Context) && castType->isArithmeticType()) return Diag(castExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) << castType << castExpr->getSourceRange(); @@ -3992,7 +4009,8 @@ Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, return ExprError(); Op.release(); - return Owned(new (Context) CStyleCastExpr(Ty->getType().getNonReferenceType(), + return Owned(new (Context) CStyleCastExpr( + Ty->getType().getNonLValueExprType(Context), Kind, castExpr, BasePath, Ty, LParenLoc, RParenLoc)); } @@ -4021,15 +4039,26 @@ Sema::ActOnCastOfParenListExpr(Scope *S, SourceLocation LParenLoc, TypeSourceInfo *TInfo) { ParenListExpr *PE = (ParenListExpr *)Op.get(); QualType Ty = TInfo->getType(); + bool isAltiVecLiteral = false; - // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' - // then handle it as such. + // Check for an altivec literal, + // i.e. all the elements are integer constants. if (getLangOptions().AltiVec && Ty->isVectorType()) { if (PE->getNumExprs() == 0) { Diag(PE->getExprLoc(), diag::err_altivec_empty_initializer); return ExprError(); } + if (PE->getNumExprs() == 1) { + if (!PE->getExpr(0)->getType()->isVectorType()) + isAltiVecLiteral = true; + } + else + isAltiVecLiteral = true; + } + // If this is an altivec initializer, '(' type ')' '(' init, ..., init ')' + // then handle it as such. + if (isAltiVecLiteral) { llvm::SmallVector<Expr *, 8> initExprs; for (unsigned i = 0, e = PE->getNumExprs(); i != e; ++i) initExprs.push_back(PE->getExpr(i)); @@ -4634,7 +4663,7 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { if (lhsType->isExtVectorType()) { if (rhsType->isExtVectorType()) return lhsType == rhsType ? Compatible : Incompatible; - if (!rhsType->isVectorType() && rhsType->isArithmeticType()) + if (rhsType->isArithmeticType()) return Compatible; } @@ -4877,7 +4906,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // The getNonReferenceType() call makes sure that the resulting expression // does not have reference type. if (result != Incompatible && rExpr->getType() != lhsType) - ImpCastExprToType(rExpr, lhsType.getNonReferenceType(), + ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), CastExpr::CK_Unknown); return result; } @@ -4932,7 +4961,7 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { // Handle the case of an ext vector and scalar. if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) { QualType EltTy = LV->getElementType(); - if (EltTy->isIntegralType() && rhsType->isIntegralType()) { + if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) { if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast); if (swapped) std::swap(rex, lex); @@ -5263,6 +5292,16 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return LHSTy; } +static bool IsWithinTemplateSpecialization(Decl *D) { + if (DeclContext *DC = D->getDeclContext()) { + if (isa<ClassTemplateSpecializationDecl>(DC)) + return true; + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) + return FD->isFunctionTemplateSpecialization(); + } + return false; +} + // C99 6.5.8, C++ [expr.rel] QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned OpaqueOpc, bool isRelational) { @@ -5272,30 +5311,55 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorCompareOperands(lex, rex, Loc, isRelational); - // C99 6.5.8p3 / C99 6.5.9p4 - if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) - UsualArithmeticConversions(lex, rex); - else { - UsualUnaryConversions(lex); - UsualUnaryConversions(rex); - } QualType lType = lex->getType(); QualType rType = rex->getType(); - if (!lType->isFloatingType() - && !(lType->isBlockPointerType() && isRelational)) { + if (!lType->hasFloatingRepresentation() && + !(lType->isBlockPointerType() && isRelational)) { // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - // NOTE: Don't warn about comparisons of enum constants. These can arise - // from macro expansions, and are usually quite deliberate. + // + // NOTE: Don't warn about comparison expressions resulting from macro + // expansion. Also don't warn about comparisons which are only self + // comparisons within a template specialization. The warnings should catch + // obvious cases in the definition of the template anyways. The idea is to + // warn when the typed comparison operator will always evaluate to the same + // result. Expr *LHSStripped = lex->IgnoreParens(); Expr *RHSStripped = rex->IgnoreParens(); - if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) - if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) - if (DRL->getDecl() == DRR->getDecl() && - !isa<EnumConstantDecl>(DRL->getDecl())) - DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison)); + if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(LHSStripped)) { + if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(RHSStripped)) { + if (DRL->getDecl() == DRR->getDecl() && !Loc.isMacroID() && + !IsWithinTemplateSpecialization(DRL->getDecl())) { + DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always) + << 0 // self- + << (Opc == BinaryOperator::EQ + || Opc == BinaryOperator::LE + || Opc == BinaryOperator::GE)); + } else if (lType->isArrayType() && rType->isArrayType() && + !DRL->getDecl()->getType()->isReferenceType() && + !DRR->getDecl()->getType()->isReferenceType()) { + // what is it always going to eval to? + char always_evals_to; + switch(Opc) { + case BinaryOperator::EQ: // e.g. array1 == array2 + always_evals_to = 0; // false + break; + case BinaryOperator::NE: // e.g. array1 != array2 + always_evals_to = 1; // true + break; + default: + // best we can say is 'a constant' + always_evals_to = 2; // e.g. array1 <= array2 + break; + } + DiagRuntimeBehavior(Loc, PDiag(diag::warn_comparison_always) + << 1 // array + << always_evals_to); + } + } + } if (isa<CastExpr>(LHSStripped)) LHSStripped = LHSStripped->IgnoreParenCasts(); @@ -5338,6 +5402,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } } + // C99 6.5.8p3 / C99 6.5.9p4 + if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) + UsualArithmeticConversions(lex, rex); + else { + UsualUnaryConversions(lex); + UsualUnaryConversions(rex); + } + + lType = lex->getType(); + rType = rex->getType(); + // The result of comparisons is 'bool' in C++, 'int' in C. QualType ResultTy = getLangOptions().CPlusPlus ? Context.BoolTy:Context.IntTy; @@ -5346,7 +5421,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return ResultTy; } else { // Check for comparisons of floating point operands using != and ==. - if (lType->isFloatingType() && rType->isFloatingType()) + if (lType->hasFloatingRepresentation()) CheckFloatComparison(Loc,lex,rex); if (lType->isArithmeticType() && rType->isArithmeticType()) @@ -5358,9 +5433,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, bool RHSIsNull = rex->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull); - // All of the following pointer related warnings are GCC extensions, except - // when handling null pointer constants. One day, we can consider making them - // errors (when -pedantic-errors is enabled). + // All of the following pointer-related warnings are GCC extensions, except + // when handling null pointer constants. if (lType->isPointerType() && rType->isPointerType()) { // C99 6.5.8p2 QualType LCanPointeeTy = Context.getCanonicalType(lType->getAs<PointerType>()->getPointeeType()); @@ -5374,10 +5448,19 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, (LCanPointeeTy->isVoidType() || RCanPointeeTy->isVoidType())) { // Valid unless comparison between non-null pointer and function pointer // This is a gcc extension compatibility comparison. + // In a SFINAE context, we treat this as a hard error to maintain + // conformance with the C++ standard. if ((LCanPointeeTy->isFunctionType() || RCanPointeeTy->isFunctionType()) && !LHSIsNull && !RHSIsNull) { - Diag(Loc, diag::ext_typecheck_comparison_of_fptr_to_void) + Diag(Loc, + isSFINAEContext()? + diag::err_typecheck_comparison_of_fptr_to_void + : diag::ext_typecheck_comparison_of_fptr_to_void) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + + if (isSFINAEContext()) + return QualType(); + ImpCastExprToType(rex, lType, CastExpr::CK_BitCast); return ResultTy; } @@ -5541,40 +5624,36 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, return ResultTy; } } - if (lType->isAnyPointerType() && rType->isIntegerType()) { + if ((lType->isAnyPointerType() && rType->isIntegerType()) || + (lType->isIntegerType() && rType->isAnyPointerType())) { unsigned DiagID = 0; - if (RHSIsNull) { - if (isRelational) + bool isError = false; + if ((LHSIsNull && lType->isIntegerType()) || + (RHSIsNull && rType->isIntegerType())) { + if (isRelational && !getLangOptions().CPlusPlus) DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; - } else if (isRelational) + } else if (isRelational && !getLangOptions().CPlusPlus) DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; - else + else if (getLangOptions().CPlusPlus) { + DiagID = diag::err_typecheck_comparison_of_pointer_integer; + isError = true; + } else DiagID = diag::ext_typecheck_comparison_of_pointer_integer; if (DiagID) { Diag(Loc, DiagID) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + if (isError) + return QualType(); } - ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer); - return ResultTy; - } - if (lType->isIntegerType() && rType->isAnyPointerType()) { - unsigned DiagID = 0; - if (LHSIsNull) { - if (isRelational) - DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_and_zero; - } else if (isRelational) - DiagID = diag::ext_typecheck_ordered_comparison_of_pointer_integer; + + if (lType->isIntegerType()) + ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer); else - DiagID = diag::ext_typecheck_comparison_of_pointer_integer; - - if (DiagID) { - Diag(Loc, DiagID) - << lType << rType << lex->getSourceRange() << rex->getSourceRange(); - } - ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer); + ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer); return ResultTy; } + // Handle block pointers. if (!isRelational && RHSIsNull && lType->isBlockPointerType() && rType->isIntegerType()) { @@ -5608,16 +5687,20 @@ QualType Sema::CheckVectorCompareOperands(Expr *&lex, Expr *&rex, // For non-floating point types, check for self-comparisons of the form // x == x, x != x, x < x, etc. These always evaluate to a constant, and // often indicate logic errors in the program. - if (!lType->isFloatingType()) { + if (!lType->hasFloatingRepresentation()) { if (DeclRefExpr* DRL = dyn_cast<DeclRefExpr>(lex->IgnoreParens())) if (DeclRefExpr* DRR = dyn_cast<DeclRefExpr>(rex->IgnoreParens())) if (DRL->getDecl() == DRR->getDecl()) - DiagRuntimeBehavior(Loc, PDiag(diag::warn_selfcomparison)); + DiagRuntimeBehavior(Loc, + PDiag(diag::warn_comparison_always) + << 0 // self- + << 2 // "a constant" + ); } // Check for comparisons of floating point operands using != and ==. - if (!isRelational && lType->isFloatingType()) { - assert (rType->isFloatingType()); + if (!isRelational && lType->hasFloatingRepresentation()) { + assert (rType->hasFloatingRepresentation()); CheckFloatComparison(Loc,lex,rex); } @@ -5652,7 +5735,25 @@ inline QualType Sema::CheckBitwiseOperands( } inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation Loc) { + Expr *&lex, Expr *&rex, SourceLocation Loc, unsigned Opc) { + + // Diagnose cases where the user write a logical and/or but probably meant a + // bitwise one. We do this when the LHS is a non-bool integer and the RHS + // is a constant. + if (lex->getType()->isIntegerType() && !lex->getType()->isBooleanType() && + rex->getType()->isIntegerType() && rex->isEvaluatable(Context) && + // Don't warn if the RHS is a (constant folded) boolean expression like + // "sizeof(int) == 4". + !rex->isKnownToHaveBooleanValue() && + // Don't warn in macros. + !Loc.isMacroID()) + Diag(Loc, diag::warn_logical_instead_of_bitwise) + << rex->getSourceRange() + << (Opc == BinaryOperator::LAnd ? "&&" : "||") + << (Opc == BinaryOperator::LAnd ? "&" : "|"); + + + if (!Context.getLangOptions().CPlusPlus) { UsualUnaryConversions(lex); UsualUnaryConversions(rex); @@ -5663,25 +5764,14 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14] return Context.IntTy; } + // The following is safe because we only use this method for + // non-overloadable operands. + // C++ [expr.log.and]p1 // C++ [expr.log.or]p1 - // The operands are both implicitly converted to type bool (clause 4). - StandardConversionSequence LHS; - if (!IsStandardConversion(lex, Context.BoolTy, - /*InOverloadResolution=*/false, LHS)) - return InvalidOperands(Loc, lex, rex); - - if (PerformImplicitConversion(lex, Context.BoolTy, LHS, - AA_Passing, /*IgnoreBaseAccess=*/false)) - return InvalidOperands(Loc, lex, rex); - - StandardConversionSequence RHS; - if (!IsStandardConversion(rex, Context.BoolTy, - /*InOverloadResolution=*/false, RHS)) - return InvalidOperands(Loc, lex, rex); - - if (PerformImplicitConversion(rex, Context.BoolTy, RHS, - AA_Passing, /*IgnoreBaseAccess=*/false)) + // The operands are both contextually converted to type bool. + if (PerformContextuallyConvertToBool(lex) || + PerformContextuallyConvertToBool(rex)) return InvalidOperands(Loc, lex, rex); // C++ [expr.log.and]p2 @@ -5786,11 +5876,22 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, QualType LHSType = LHS->getType(); QualType RHSType = CompoundType.isNull() ? RHS->getType() : CompoundType; - AssignConvertType ConvTy; if (CompoundType.isNull()) { + QualType LHSTy(LHSType); // Simple assignment "x = y". - ConvTy = CheckSingleAssignmentConstraints(LHSType, RHS); + if (const ObjCImplicitSetterGetterRefExpr *OISGE = + dyn_cast<ObjCImplicitSetterGetterRefExpr>(LHS)) { + // If using property-dot syntax notation for assignment, and there is a + // setter, RHS expression is being passed to the setter argument. So, + // type conversion (and comparison) is RHS to setter's argument type. + if (const ObjCMethodDecl *SetterMD = OISGE->getSetterMethod()) { + ObjCMethodDecl::param_iterator P = SetterMD->param_begin(); + LHSTy = (*P)->getType(); + } + } + + ConvTy = CheckSingleAssignmentConstraints(LHSTy, RHS); // Special case of NSObject attributes on c-style pointer types. if (ConvTy == IncompatiblePointer && ((Context.isObjCNSObjectType(LHSType) && @@ -5829,6 +5930,23 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, RHS, AA_Assigning)) return QualType(); + + // Check to see if the destination operand is a dereferenced null pointer. If + // so, and if not volatile-qualified, this is undefined behavior that the + // optimizer will delete, so warn about it. People sometimes try to use this + // to get a deterministic trap and are surprised by clang's behavior. This + // only handles the pattern "*null = whatever", which is a very syntactic + // check. + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(LHS->IgnoreParenCasts())) + if (UO->getOpcode() == UnaryOperator::Deref && + UO->getSubExpr()->IgnoreParenCasts()-> + isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull) && + !UO->getType().isVolatileQualified()) { + Diag(UO->getOperatorLoc(), diag::warn_indirection_through_null) + << UO->getSubExpr()->getSourceRange(); + Diag(UO->getOperatorLoc(), diag::note_indirection_through_null); + } + // C99 6.5.16p3: The type of an assignment expression is the type of the // left operand unless the left operand has qualified type, in which case // it is the unqualified version of the type of the left operand. @@ -5841,6 +5959,8 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // C99 6.5.17 QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) { + DiagnoseUnusedExprResult(LHS); + // Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions. // C++ does not perform this conversion (C++ [expr.comma]p1). if (!getLangOptions().CPlusPlus) @@ -6025,13 +6145,17 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { return Context.getMemberPointerType(op->getType(), Context.getTypeDeclType(cast<RecordDecl>(dcl->getDeclContext())) .getTypePtr()); - } else if (lval == Expr::LV_ClassTemporary) { + } + + if (lval == Expr::LV_ClassTemporary) { Diag(OpLoc, isSFINAEContext()? diag::err_typecheck_addrof_class_temporary : diag::ext_typecheck_addrof_class_temporary) << op->getType() << op->getSourceRange(); if (isSFINAEContext()) return QualType(); - } else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { + } else if (isa<ObjCSelectorExpr>(op)) + return Context.getPointerType(op->getType()); + else if (lval != Expr::LV_Valid && lval != Expr::LV_IncompleteVoidType) { // C99 6.5.3.2p1 // The operand must be either an l-value or a function designator if (!op->getType()->isFunctionType()) { @@ -6112,26 +6236,32 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { return Context.getPointerType(op->getType()); } +/// CheckIndirectionOperand - Type check unary indirection (prefix '*'). QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) { if (Op->isTypeDependent()) return Context.DependentTy; UsualUnaryConversions(Op); - QualType Ty = Op->getType(); - - // Note that per both C89 and C99, this is always legal, even if ptype is an - // incomplete type or void. It would be possible to warn about dereferencing - // a void pointer, but it's completely well-defined, and such a warning is - // unlikely to catch any mistakes. - if (const PointerType *PT = Ty->getAs<PointerType>()) - return PT->getPointeeType(); - - if (const ObjCObjectPointerType *OPT = Ty->getAs<ObjCObjectPointerType>()) - return OPT->getPointeeType(); - - Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer) - << Ty << Op->getSourceRange(); - return QualType(); + QualType OpTy = Op->getType(); + QualType Result; + + // Note that per both C89 and C99, indirection is always legal, even if OpTy + // is an incomplete type or void. It would be possible to warn about + // dereferencing a void pointer, but it's completely well-defined, and such a + // warning is unlikely to catch any mistakes. + if (const PointerType *PT = OpTy->getAs<PointerType>()) + Result = PT->getPointeeType(); + else if (const ObjCObjectPointerType *OPT = + OpTy->getAs<ObjCObjectPointerType>()) + Result = OPT->getPointeeType(); + + if (Result.isNull()) { + Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer) + << OpTy << Op->getSourceRange(); + return QualType(); + } + + return Result; } static inline BinaryOperator::Opcode ConvertTokenKindToBinaryOpcode( @@ -6251,7 +6381,7 @@ Action::OwningExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc, break; case BinaryOperator::LAnd: case BinaryOperator::LOr: - ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc); + ResultTy = CheckLogicalOperands(lhs, rhs, OpLoc, Opc); break; case BinaryOperator::MulAssign: case BinaryOperator::DivAssign: @@ -6479,7 +6609,8 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType = Input->getType(); if (resultType->isDependentType()) break; - if (resultType->isArithmeticType()) // C99 6.5.3.3p1 + if (resultType->isArithmeticType() || // C99 6.5.3.3p1 + resultType->isVectorType()) break; else if (getLangOptions().CPlusPlus && // C++ [expr.unary.op]p6-7 resultType->isEnumeralType()) @@ -6980,83 +7111,99 @@ void Sema::ActOnBlockStart(SourceLocation CaretLoc, Scope *BlockScope) { BlockDecl *Block = BlockDecl::Create(Context, CurContext, CaretLoc); PushBlockScope(BlockScope, Block); CurContext->addDecl(Block); - PushDeclContext(BlockScope, Block); + if (BlockScope) + PushDeclContext(BlockScope, Block); + else + CurContext = Block; } void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!"); BlockScopeInfo *CurBlock = getCurBlock(); - if (ParamInfo.getNumTypeObjects() == 0 - || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) { - ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); - QualType T = GetTypeForDeclarator(ParamInfo, CurScope); - - if (T->isArrayType()) { - Diag(ParamInfo.getSourceRange().getBegin(), - diag::err_block_returns_array); - return; - } - - // The parameter list is optional, if there was none, assume (). - if (!T->isFunctionType()) - T = Context.getFunctionType(T, 0, 0, false, 0, false, false, 0, 0, - FunctionType::ExtInfo()); + TypeSourceInfo *Sig = GetTypeForDeclarator(ParamInfo, CurScope); + CurBlock->TheDecl->setSignatureAsWritten(Sig); + QualType T = Sig->getType(); + + bool isVariadic; + QualType RetTy; + if (const FunctionType *Fn = T->getAs<FunctionType>()) { + CurBlock->FunctionType = T; + RetTy = Fn->getResultType(); + isVariadic = + !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic(); + } else { + RetTy = T; + isVariadic = false; + } - CurBlock->hasPrototype = true; - CurBlock->isVariadic = false; - // Check for a valid sentinel attribute on this block. - if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { - Diag(ParamInfo.getAttributes()->getLoc(), - diag::warn_attribute_sentinel_not_variadic) << 1; - // FIXME: remove the attribute. - } - QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType(); + CurBlock->TheDecl->setIsVariadic(isVariadic); - // Do not allow returning a objc interface by-value. - if (RetTy->isObjCObjectType()) { - Diag(ParamInfo.getSourceRange().getBegin(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; - return; - } + // Don't allow returning an array by value. + if (RetTy->isArrayType()) { + Diag(ParamInfo.getSourceRange().getBegin(), diag::err_block_returns_array); + return; + } - CurBlock->ReturnType = RetTy; + // Don't allow returning a objc interface by value. + if (RetTy->isObjCObjectType()) { + Diag(ParamInfo.getSourceRange().getBegin(), + diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; return; } - // Analyze arguments to block. - assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Not a function declarator!"); - DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun; - - CurBlock->hasPrototype = FTI.hasPrototype; - CurBlock->isVariadic = true; - - // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes - // no arguments, not a function that takes a single void argument. - if (FTI.hasPrototype && - FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 && - (!FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType().getCVRQualifiers()&& - FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType())) { - // empty arg list, don't push any params. - CurBlock->isVariadic = false; - } else if (FTI.hasPrototype) { - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { - ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); + // Context.DependentTy is used as a placeholder for a missing block + // return type. TODO: what should we do with declarators like: + // ^ * { ... } + // If the answer is "apply template argument deduction".... + if (RetTy != Context.DependentTy) + CurBlock->ReturnType = RetTy; + + // Push block parameters from the declarator if we had them. + llvm::SmallVector<ParmVarDecl*, 8> Params; + if (isa<FunctionProtoType>(T)) { + FunctionProtoTypeLoc TL = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc()); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + ParmVarDecl *Param = TL.getArg(I); if (Param->getIdentifier() == 0 && !Param->isImplicit() && !Param->isInvalidDecl() && !getLangOptions().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); - CurBlock->Params.push_back(Param); + Params.push_back(Param); + } + + // Fake up parameter variables if we have a typedef, like + // ^ fntype { ... } + } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) { + for (FunctionProtoType::arg_type_iterator + I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) { + ParmVarDecl *Param = + BuildParmVarDeclForTypedef(CurBlock->TheDecl, + ParamInfo.getSourceRange().getBegin(), + *I); + Params.push_back(Param); } - CurBlock->isVariadic = FTI.isVariadic; } - CurBlock->TheDecl->setParams(CurBlock->Params.data(), - CurBlock->Params.size()); - CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); + + // Set the parameters on the block decl. + if (!Params.empty()) + CurBlock->TheDecl->setParams(Params.data(), Params.size()); + + // Finally we can process decl attributes. ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); + if (!isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) { + Diag(ParamInfo.getAttributes()->getLoc(), + diag::warn_attribute_sentinel_not_variadic) << 1; + // FIXME: remove the attribute. + } + + // Put the parameter variables in scope. We can bail out immediately + // if we don't have any. + if (Params.empty()) + return; + bool ShouldCheckShadow = Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored; @@ -7072,25 +7219,6 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { PushOnScopeChains(*AI, CurBlock->TheScope); } } - - // Check for a valid sentinel attribute on this block. - if (!CurBlock->isVariadic && - CurBlock->TheDecl->getAttr<SentinelAttr>()) { - Diag(ParamInfo.getAttributes()->getLoc(), - diag::warn_attribute_sentinel_not_variadic) << 1; - // FIXME: remove the attribute. - } - - // Analyze the return type. - QualType T = GetTypeForDeclarator(ParamInfo, CurScope); - QualType RetTy = T->getAs<FunctionType>()->getResultType(); - - // Do not allow returning a objc interface by-value. - if (RetTy->isObjCObjectType()) { - Diag(ParamInfo.getSourceRange().getBegin(), - diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; - } else if (!RetTy->isDependentType()) - CurBlock->ReturnType = RetTy; } /// ActOnBlockError - If there is an error parsing a block, this callback @@ -7111,29 +7239,59 @@ Sema::OwningExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, Diag(CaretLoc, diag::err_blocks_disable); BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); - + PopDeclContext(); QualType RetTy = Context.VoidTy; if (!BSI->ReturnType.isNull()) RetTy = BSI->ReturnType; - llvm::SmallVector<QualType, 8> ArgTypes; - for (unsigned i = 0, e = BSI->Params.size(); i != e; ++i) - ArgTypes.push_back(BSI->Params[i]->getType()); - bool NoReturn = BSI->TheDecl->getAttr<NoReturnAttr>(); QualType BlockTy; - if (!BSI->hasPrototype) - BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, 0, CC_Default)); - else - BlockTy = Context.getFunctionType(RetTy, ArgTypes.data(), ArgTypes.size(), - BSI->isVariadic, 0, false, false, 0, 0, - FunctionType::ExtInfo(NoReturn, 0, CC_Default)); + + // If the user wrote a function type in some form, try to use that. + if (!BSI->FunctionType.isNull()) { + const FunctionType *FTy = BSI->FunctionType->getAs<FunctionType>(); + + FunctionType::ExtInfo Ext = FTy->getExtInfo(); + if (NoReturn && !Ext.getNoReturn()) Ext = Ext.withNoReturn(true); + + // Turn protoless block types into nullary block types. + if (isa<FunctionNoProtoType>(FTy)) { + BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, + false, false, 0, 0, Ext); + + // Otherwise, if we don't need to change anything about the function type, + // preserve its sugar structure. + } else if (FTy->getResultType() == RetTy && + (!NoReturn || FTy->getNoReturnAttr())) { + BlockTy = BSI->FunctionType; + + // Otherwise, make the minimal modifications to the function type. + } else { + const FunctionProtoType *FPT = cast<FunctionProtoType>(FTy); + BlockTy = Context.getFunctionType(RetTy, + FPT->arg_type_begin(), + FPT->getNumArgs(), + FPT->isVariadic(), + /*quals*/ 0, + FPT->hasExceptionSpec(), + FPT->hasAnyExceptionSpec(), + FPT->getNumExceptions(), + FPT->exception_begin(), + Ext); + } + + // If we don't have a function type, just build one from nothing. + } else { + BlockTy = Context.getFunctionType(RetTy, 0, 0, false, 0, + false, false, 0, 0, + FunctionType::ExtInfo(NoReturn, 0, CC_Default)); + } // FIXME: Check that return/parameter types are complete/non-abstract - DiagnoseUnusedParameters(BSI->Params.begin(), BSI->Params.end()); + DiagnoseUnusedParameters(BSI->TheDecl->param_begin(), + BSI->TheDecl->param_end()); BlockTy = Context.getBlockPointerType(BlockTy); // If needed, diagnose invalid gotos and switches in the block. @@ -7210,7 +7368,8 @@ Sema::OwningExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc, // FIXME: Warn if a non-POD type is passed in. expr.release(); - return Owned(new (Context) VAArgExpr(BuiltinLoc, E, T.getNonReferenceType(), + return Owned(new (Context) VAArgExpr(BuiltinLoc, E, + T.getNonLValueExprType(Context), RPLoc)); } @@ -7445,7 +7604,7 @@ Sema::PopExpressionEvaluationContext() { void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { assert(D && "No declaration?"); - if (D->isUsed()) + if (D->isUsed(false)) return; // Mark a parameter or variable declaration "used", regardless of whether we're in a @@ -7488,24 +7647,24 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { unsigned TypeQuals; if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) { - if (!Constructor->isUsed()) + if (!Constructor->isUsed(false)) DefineImplicitDefaultConstructor(Loc, Constructor); } else if (Constructor->isImplicit() && Constructor->isCopyConstructor(TypeQuals)) { - if (!Constructor->isUsed()) + if (!Constructor->isUsed(false)) DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals); } MarkVTableUsed(Loc, Constructor->getParent()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { - if (Destructor->isImplicit() && !Destructor->isUsed()) + if (Destructor->isImplicit() && !Destructor->isUsed(false)) DefineImplicitDestructor(Loc, Destructor); if (Destructor->isVirtual()) MarkVTableUsed(Loc, Destructor->getParent()); } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) { if (MethodDecl->isImplicit() && MethodDecl->isOverloadedOperator() && MethodDecl->getOverloadedOperator() == OO_Equal) { - if (!MethodDecl->isUsed()) + if (!MethodDecl->isUsed(false)) DefineImplicitCopyAssignment(Loc, MethodDecl); } else if (MethodDecl->isVirtual()) MarkVTableUsed(Loc, MethodDecl->getParent()); @@ -7569,45 +7728,46 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { } namespace { - // Mark all of the declarations referenced + // Mark all of the declarations referenced // FIXME: Not fully implemented yet! We need to have a better understanding - // of when we're entering + // of when we're entering class MarkReferencedDecls : public RecursiveASTVisitor<MarkReferencedDecls> { Sema &S; SourceLocation Loc; - + public: typedef RecursiveASTVisitor<MarkReferencedDecls> Inherited; - + MarkReferencedDecls(Sema &S, SourceLocation Loc) : S(S), Loc(Loc) { } - - bool VisitTemplateArgument(const TemplateArgument &Arg); - bool VisitRecordType(RecordType *T); + + bool TraverseTemplateArgument(const TemplateArgument &Arg); + bool TraverseRecordType(RecordType *T); }; } -bool MarkReferencedDecls::VisitTemplateArgument(const TemplateArgument &Arg) { +bool MarkReferencedDecls::TraverseTemplateArgument( + const TemplateArgument &Arg) { if (Arg.getKind() == TemplateArgument::Declaration) { S.MarkDeclarationReferenced(Loc, Arg.getAsDecl()); } - - return Inherited::VisitTemplateArgument(Arg); + + return Inherited::TraverseTemplateArgument(Arg); } -bool MarkReferencedDecls::VisitRecordType(RecordType *T) { +bool MarkReferencedDecls::TraverseRecordType(RecordType *T) { if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(T->getDecl())) { const TemplateArgumentList &Args = Spec->getTemplateArgs(); - return VisitTemplateArguments(Args.getFlatArgumentList(), - Args.flat_size()); + return TraverseTemplateArguments(Args.getFlatArgumentList(), + Args.flat_size()); } - return false; + return true; } void Sema::MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T) { MarkReferencedDecls Marker(*this, Loc); - Marker.Visit(Context.getCanonicalType(T)); + Marker.TraverseType(Context.getCanonicalType(T)); } /// \brief Emit a diagnostic that describes an effect on the run-time behavior diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp index 97de96a..090400f 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprCXX.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -52,6 +53,8 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, // } // // See also PR6358 and PR6359. + // For this reason, we're currently only doing the C++03 version of this + // code; the C++0x version has to wait until we get a proper spec. QualType SearchType; DeclContext *LookupCtx = 0; bool isDependent = false; @@ -68,50 +71,33 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, bool AlreadySearched = false; bool LookAtPrefix = true; - if (!getLangOptions().CPlusPlus0x) { - // C++ [basic.lookup.qual]p6: - // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, - // the type-names are looked up as types in the scope designated by the - // nested-name-specifier. In a qualified-id of the form: - // - // ::[opt] nested-name-specifier ̃ class-name - // - // where the nested-name-specifier designates a namespace scope, and in - // a qualified-id of the form: - // - // ::opt nested-name-specifier class-name :: ̃ class-name - // - // the class-names are looked up as types in the scope designated by - // the nested-name-specifier. - // - // Here, we check the first case (completely) and determine whether the - // code below is permitted to look at the prefix of the - // nested-name-specifier (as we do in C++0x). - DeclContext *DC = computeDeclContext(SS, EnteringContext); - if (DC && DC->isFileContext()) { - AlreadySearched = true; - LookupCtx = DC; - isDependent = false; - } else if (DC && isa<CXXRecordDecl>(DC)) - LookAtPrefix = false; - } - - // C++0x [basic.lookup.qual]p6: - // If a pseudo-destructor-name (5.2.4) contains a - // nested-name-specifier, the type-names are looked up as types - // in the scope designated by the nested-name-specifier. Similarly, in - // a qualified-id of the form: + // C++ [basic.lookup.qual]p6: + // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, + // the type-names are looked up as types in the scope designated by the + // nested-name-specifier. In a qualified-id of the form: + // + // ::[opt] nested-name-specifier ̃ class-name // - // :: [opt] nested-name-specifier[opt] class-name :: ~class-name + // where the nested-name-specifier designates a namespace scope, and in + // a qualified-id of the form: // - // the second class-name is looked up in the same scope as the first. + // ::opt nested-name-specifier class-name :: ̃ class-name // - // To implement this, we look at the prefix of the - // nested-name-specifier we were given, and determine the lookup - // context from that. + // the class-names are looked up as types in the scope designated by + // the nested-name-specifier. // - // We also fold in the second case from the C++03 rules quoted further - // above. + // Here, we check the first case (completely) and determine whether the + // code below is permitted to look at the prefix of the + // nested-name-specifier. + DeclContext *DC = computeDeclContext(SS, EnteringContext); + if (DC && DC->isFileContext()) { + AlreadySearched = true; + LookupCtx = DC; + isDependent = false; + } else if (DC && isa<CXXRecordDecl>(DC)) + LookAtPrefix = false; + + // The second case from the C++03 rules quoted further above. NestedNameSpecifier *Prefix = 0; if (AlreadySearched) { // Nothing left to do. @@ -120,11 +106,6 @@ Action::TypeTy *Sema::getDestructorName(SourceLocation TildeLoc, PrefixSS.setScopeRep(Prefix); LookupCtx = computeDeclContext(PrefixSS, EnteringContext); isDependent = isDependentScopeSpecifier(PrefixSS); - } else if (getLangOptions().CPlusPlus0x && - (LookupCtx = computeDeclContext(SS, EnteringContext))) { - if (!LookupCtx->isTranslationUnit()) - LookupCtx = LookupCtx->getParent(); - isDependent = LookupCtx && LookupCtx->isDependentContext(); } else if (ObjectTypePtr) { LookupCtx = computeDeclContext(SearchType); isDependent = SearchType->isDependentType(); @@ -284,7 +265,10 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, // that is the operand of typeid are always ignored. // If the type of the type-id is a class type or a reference to a class // type, the class shall be completely-defined. - QualType T = Operand->getType().getNonReferenceType(); + Qualifiers Quals; + QualType T + = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(), + Quals); if (T->getAs<RecordType>() && RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) return ExprError(); @@ -328,9 +312,11 @@ Sema::OwningExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, // cv-qualified type, the result of the typeid expression refers to a // std::type_info object representing the cv-unqualified referenced // type. - if (T.hasQualifiers()) { - ImpCastExprToType(E, T.getUnqualifiedType(), CastExpr::CK_NoOp, - E->isLvalue(Context)); + Qualifiers Quals; + QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); + if (!Context.hasSameType(T, UnqualT)) { + T = UnqualT; + ImpCastExprToType(E, UnqualT, CastExpr::CK_NoOp, E->isLvalue(Context)); Operand.release(); Operand = Owned(E); } @@ -453,11 +439,28 @@ bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E) { return true; E = Res.takeAs<Expr>(); + // If the exception has class type, we need additional handling. + const RecordType *RecordTy = Ty->getAs<RecordType>(); + if (!RecordTy) + return false; + CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); + // If we are throwing a polymorphic class type or pointer thereof, // exception handling will make use of the vtable. - if (const RecordType *RecordTy = Ty->getAs<RecordType>()) - MarkVTableUsed(ThrowLoc, cast<CXXRecordDecl>(RecordTy->getDecl())); - + MarkVTableUsed(ThrowLoc, RD); + + // If the class has a non-trivial destructor, we must be able to call it. + if (RD->hasTrivialDestructor()) + return false; + + CXXDestructorDecl *Destructor + = const_cast<CXXDestructorDecl*>(LookupDestructor(RD)); + if (!Destructor) + return false; + + MarkDeclarationReferenced(E->getExprLoc(), Destructor); + CheckDestructorAccess(E->getExprLoc(), Destructor, + PDiag(diag::err_access_dtor_exception) << Ty); return false; } @@ -537,33 +540,26 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, exprs.release(); - return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(), + return Owned(new (Context) CXXFunctionalCastExpr( + Ty.getNonLValueExprType(Context), TInfo, TyBeginLoc, Kind, Exprs[0], BasePath, RParenLoc)); } - if (const RecordType *RT = Ty->getAs<RecordType>()) { - CXXRecordDecl *Record = cast<CXXRecordDecl>(RT->getDecl()); - - if (NumExprs > 1 || !Record->hasTrivialConstructor() || - !Record->hasTrivialDestructor()) { - InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty); - InitializationKind Kind - = NumExprs ? InitializationKind::CreateDirect(TypeRange.getBegin(), - LParenLoc, RParenLoc) - : InitializationKind::CreateValue(TypeRange.getBegin(), - LParenLoc, RParenLoc); - InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); - OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, - move(exprs)); - - // FIXME: Improve AST representation? - return move(Result); - } - - // Fall through to value-initialize an object of class type that - // doesn't have a user-declared default constructor. + if (Ty->isRecordType()) { + InitializedEntity Entity = InitializedEntity::InitializeTemporary(Ty); + InitializationKind Kind + = NumExprs ? InitializationKind::CreateDirect(TypeRange.getBegin(), + LParenLoc, RParenLoc) + : InitializationKind::CreateValue(TypeRange.getBegin(), + LParenLoc, RParenLoc); + InitializationSequence InitSeq(*this, Entity, Kind, Exprs, NumExprs); + OwningExprResult Result = InitSeq.Perform(*this, Entity, Kind, + move(exprs)); + + // FIXME: Improve AST representation? + return move(Result); } // C++ [expr.type.conv]p1: @@ -582,7 +578,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, // rvalue of the specified type, which is value-initialized. // exprs.release(); - return Owned(new (Context) CXXZeroInitValueExpr(Ty, TyBeginLoc, RParenLoc)); + return Owned(new (Context) CXXScalarValueInitExpr(Ty, TyBeginLoc, RParenLoc)); } @@ -594,7 +590,7 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, Action::OwningExprResult Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, - SourceLocation PlacementRParen, bool ParenTypeId, + SourceLocation PlacementRParen, SourceRange TypeIdParens, Declarator &D, SourceLocation ConstructorLParen, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen) { @@ -610,17 +606,6 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) << D.getSourceRange()); - if (ParenTypeId) { - // Can't have dynamic array size when the type-id is in parentheses. - Expr *NumElts = (Expr *)Chunk.Arr.NumElts; - if (!NumElts->isTypeDependent() && !NumElts->isValueDependent() && - !NumElts->isIntegerConstantExpr(Context)) { - Diag(D.getTypeObject(0).Loc, diag::err_new_paren_array_nonconst) - << NumElts->getSourceRange(); - return ExprError(); - } - } - ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); D.DropFirstTypeObject(); } @@ -644,19 +629,20 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, } //FIXME: Store TypeSourceInfo in CXXNew expression. - TypeSourceInfo *TInfo = 0; - QualType AllocType = GetTypeForDeclarator(D, /*Scope=*/0, &TInfo); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/0); + QualType AllocType = TInfo->getType(); if (D.isInvalidType()) return ExprError(); - + + SourceRange R = TInfo->getTypeLoc().getSourceRange(); return BuildCXXNew(StartLoc, UseGlobal, PlacementLParen, move(PlacementArgs), PlacementRParen, - ParenTypeId, + TypeIdParens, AllocType, D.getSourceRange().getBegin(), - D.getSourceRange(), + R, Owned(ArraySize), ConstructorLParen, move(ConstructorArgs), @@ -668,7 +654,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - bool ParenTypeId, + SourceRange TypeIdParens, QualType AllocType, SourceLocation TypeLoc, SourceRange TypeRange, @@ -697,11 +683,29 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, // or enumeration type with a non-negative value." Expr *ArraySize = (Expr *)ArraySizeE.get(); if (ArraySize && !ArraySize->isTypeDependent()) { + QualType SizeType = ArraySize->getType(); - if (!SizeType->isIntegralType() && !SizeType->isEnumeralType()) - return ExprError(Diag(ArraySize->getSourceRange().getBegin(), - diag::err_array_size_not_integral) - << SizeType << ArraySize->getSourceRange()); + + OwningExprResult ConvertedSize + = ConvertToIntegralOrEnumerationType(StartLoc, move(ArraySizeE), + PDiag(diag::err_array_size_not_integral), + PDiag(diag::err_array_size_incomplete_type) + << ArraySize->getSourceRange(), + PDiag(diag::err_array_size_explicit_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(diag::err_array_size_ambiguous_conversion), + PDiag(diag::note_array_size_conversion), + PDiag(getLangOptions().CPlusPlus0x? 0 + : diag::ext_array_size_conversion)); + if (ConvertedSize.isInvalid()) + return ExprError(); + + ArraySize = ConvertedSize.takeAs<Expr>(); + ArraySizeE = Owned(ArraySize); + SizeType = ArraySize->getType(); + if (!SizeType->isIntegralOrEnumerationType()) + return ExprError(); + // Let's see if this is a constant < 0. If so, we reject it out of hand. // We don't care about special rules, so we tell the machinery it's not // evaluated - it gives us a result in more cases. @@ -714,6 +718,14 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(ArraySize->getSourceRange().getBegin(), diag::err_typecheck_negative_array_size) << ArraySize->getSourceRange()); + } else if (TypeIdParens.isValid()) { + // Can't have dynamic array size when the type-id is in parentheses. + Diag(ArraySize->getLocStart(), diag::ext_new_paren_array_nonconst) + << ArraySize->getSourceRange() + << FixItHint::CreateRemoval(TypeIdParens.getBegin()) + << FixItHint::CreateRemoval(TypeIdParens.getEnd()); + + TypeIdParens = SourceRange(); } } @@ -828,13 +840,15 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, PlacementArgs.release(); ConstructorArgs.release(); ArraySizeE.release(); + + // FIXME: The TypeSourceInfo should also be included in CXXNewExpr. return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, - PlaceArgs, NumPlaceArgs, ParenTypeId, + PlaceArgs, NumPlaceArgs, TypeIdParens, ArraySize, Constructor, Init, ConsArgs, NumConsArgs, OperatorDelete, ResultType, StartLoc, Init ? ConstructorRParen : - SourceLocation())); + TypeRange.getEnd())); } /// CheckAllocatedType - Checks that a type is suitable as the allocated type @@ -1181,20 +1195,11 @@ void Sema::DeclareGlobalNewDelete() { // "std" or "bad_alloc" as necessary to form the exception specification. // However, we do not make these implicit declarations visible to name // lookup. - if (!StdNamespace) { - // The "std" namespace has not yet been defined, so build one implicitly. - StdNamespace = NamespaceDecl::Create(Context, - Context.getTranslationUnitDecl(), - SourceLocation(), - &PP.getIdentifierTable().get("std")); - StdNamespace->setImplicit(true); - } - if (!StdBadAlloc) { // The "std::bad_alloc" class has not yet been declared, so build it // implicitly. StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, - StdNamespace, + getStdNamespace(), SourceLocation(), &PP.getIdentifierTable().get("bad_alloc"), SourceLocation(), 0); @@ -1291,11 +1296,15 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, if (Found.isAmbiguous()) return true; + Found.suppressDiagnostics(); + for (LookupResult::iterator F = Found.begin(), FEnd = Found.end(); F != FEnd; ++F) { if (CXXMethodDecl *Delete = dyn_cast<CXXMethodDecl>(*F)) if (Delete->isUsualDeallocationFunction()) { Operator = Delete; + CheckAllocationAccess(StartLoc, SourceRange(), Found.getNamingClass(), + F.getPair()); return false; } } @@ -1436,7 +1445,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal, return ExprError(); if (!RD->hasTrivialDestructor()) - if (const CXXDestructorDecl *Dtor = RD->getDestructor(Context)) + if (const CXXDestructorDecl *Dtor = LookupDestructor(RD)) MarkDeclarationReferenced(StartLoc, const_cast<CXXDestructorDecl*>(Dtor)); } @@ -1517,7 +1526,7 @@ Sema::IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType) { // be converted to an rvalue of type "pointer to char"; a wide // string literal can be converted to an rvalue of type "pointer // to wchar_t" (C++ 4.2p2). - if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From)) + if (StringLiteral *StrLit = dyn_cast<StringLiteral>(From->IgnoreParens())) if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) if (const BuiltinType *ToPointeeType = ToPtrType->getPointeeType()->getAs<BuiltinType>()) { @@ -1776,7 +1785,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; case ICK_Floating_Integral: - if (ToType->isFloatingType()) + if (ToType->isRealFloatingType()) ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating); else ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral); @@ -1871,7 +1880,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ICK_Qualification: // FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue // references. - ImpCastExprToType(From, ToType.getNonReferenceType(), + ImpCastExprToType(From, ToType.getNonLValueExprType(Context), CastExpr::CK_NoOp, ToType->isLValueReferenceType()); if (SCS.DeprecatedStringLiteralToCharPtr) @@ -1973,7 +1982,7 @@ QualType Sema::CheckPointerToMemberOperands( BasePath); } - if (isa<CXXZeroInitValueExpr>(rex->IgnoreParens())) { + if (isa<CXXScalarValueInitExpr>(rex->IgnoreParens())) { // Diagnose use of pointer-to-member type which when used as // the functional cast in a pointer-to-member expression. Diag(Loc, diag::err_pointer_to_member_type) << isIndirect; @@ -2583,6 +2592,16 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (FTy->getResultType()->isReferenceType()) return Owned(E); } + else if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { + QualType Ty = ME->getType(); + if (const PointerType *PT = Ty->getAs<PointerType>()) + Ty = PT->getPointeeType(); + else if (const BlockPointerType *BPT = Ty->getAs<BlockPointerType>()) + Ty = BPT->getPointeeType(); + if (Ty->isReferenceType()) + return Owned(E); + } + // That should be enough to guarantee that this type is complete. // If it has a trivial destructor, we can avoid the extra copy. @@ -2590,11 +2609,9 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (RD->hasTrivialDestructor()) return Owned(E); - CXXTemporary *Temp = CXXTemporary::Create(Context, - RD->getDestructor(Context)); + CXXTemporary *Temp = CXXTemporary::Create(Context, LookupDestructor(RD)); ExprTemporaries.push_back(Temp); - if (CXXDestructorDecl *Destructor = - const_cast<CXXDestructorDecl*>(RD->getDestructor(Context))) { + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { MarkDeclarationReferenced(E->getExprLoc(), Destructor); CheckDestructorAccess(E->getExprLoc(), Destructor, PDiag(diag::err_access_dtor_temp) @@ -2819,7 +2836,7 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base, if (ScopeTypeInfo) { QualType ScopeType = ScopeTypeInfo->getType(); if (!ScopeType->isDependentType() && !ObjectType->isDependentType() && - !Context.hasSameType(ScopeType, ObjectType)) { + !Context.hasSameUnqualifiedType(ScopeType, ObjectType)) { Diag(ScopeTypeInfo->getTypeLoc().getLocalSourceRange().getBegin(), diag::err_pseudo_dtor_type_mismatch) @@ -2891,7 +2908,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base, // record types and dependent types matter. void *ObjectTypePtrForLookup = 0; if (!SS.isSet()) { - ObjectTypePtrForLookup = (void *)ObjectType->getAs<RecordType>(); + ObjectTypePtrForLookup = const_cast<RecordType*>( + ObjectType->getAs<RecordType>()); if (!ObjectTypePtrForLookup && ObjectType->isDependentType()) ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr(); } @@ -3012,7 +3030,7 @@ CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, MemberExpr *ME = new (Context) MemberExpr(Exp, /*IsArrow=*/false, Method, SourceLocation(), Method->getType()); - QualType ResultType = Method->getResultType().getNonReferenceType(); + QualType ResultType = Method->getCallResultType(); MarkDeclarationReferenced(Exp->getLocStart(), Method); CXXMemberCallExpr *CE = new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp index 695a1be..9f43471 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaExprObjC.cpp @@ -207,7 +207,7 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, return false; } - ReturnType = Method->getResultType().getNonReferenceType(); + ReturnType = Method->getSendResultType(); unsigned NumNamedArgs = Sel.getNumArgs(); // Method might have more arguments than selector indicates. This is due @@ -346,7 +346,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, Selector Sel = PP.getSelectorTable().getNullarySelector(Member); ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) - ResTy = Getter->getResultType(); + ResTy = Getter->getSendResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, MemberLoc, BaseExpr)); } @@ -402,7 +402,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, if (Getter) { QualType PType; - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); return Owned(new (Context) ObjCImplicitSetterGetterRefExpr(Getter, PType, Setter, MemberLoc, BaseExpr)); } @@ -510,7 +510,7 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName, QualType PType; if (Getter) - PType = Getter->getResultType(); + PType = Getter->getSendResultType(); else { for (ObjCMethodDecl::param_iterator PI = Setter->param_begin(), E = Setter->param_end(); PI != E; ++PI) @@ -1007,6 +1007,12 @@ Sema::OwningExprResult Sema::BuildInstanceMessage(ExprArg ReceiverE, if (CheckMessageArgumentTypes(Args, NumArgs, Sel, Method, false, LBracLoc, RBracLoc, ReturnType)) return ExprError(); + + if (!ReturnType->isVoidType()) { + if (RequireCompleteType(LBracLoc, ReturnType, + diag::err_illegal_message_expr_incomplete_type)) + return ExprError(); + } // Construct the appropriate ObjCMessageExpr instance. Expr *Result; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp index 20f0c79..7ad1775 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.cpp @@ -523,8 +523,9 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, StructuredList->setSyntacticForm(IList); CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, Index, StructuredList, StructuredIndex, TopLevelObject); - IList->setType(T.getNonReferenceType()); - StructuredList->setType(T.getNonReferenceType()); + QualType ExprTy = T.getNonLValueExprType(SemaRef.Context); + IList->setType(ExprTy); + StructuredList->setType(ExprTy); if (hadError) return; @@ -877,10 +878,15 @@ void InitListChecker::CheckVectorType(const InitializedEntity &Entity, StructuredList, StructuredIndex); ++numEltsInit; } else { + QualType VecType; const VectorType *IVT = IType->getAs<VectorType>(); unsigned numIElts = IVT->getNumElements(); - QualType VecType = SemaRef.Context.getExtVectorType(elementType, - numIElts); + + if (IType->isExtVectorType()) + VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); + else + VecType = SemaRef.Context.getVectorType(elementType, numIElts, + IVT->getAltiVecSpecific()); CheckSubElementType(ElementEntity, IList, VecType, Index, StructuredList, StructuredIndex); numEltsInit += numIElts; @@ -1114,7 +1120,7 @@ void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, } // Emit warnings for missing struct field initializers. - if (CheckForMissingFields && Field != FieldEnd && + if (InitializedSomething && CheckForMissingFields && Field != FieldEnd && !Field->getType()->isIncompleteArrayType() && !DeclType->isUnionType()) { // It is possible we have one or more unnamed bitfields remaining. // Find first (if any) named field and emit warning. @@ -1711,7 +1717,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, InitRange.getBegin(), 0, 0, InitRange.getEnd()); - Result->setType(CurrentObjectType.getNonReferenceType()); + Result->setType(CurrentObjectType.getNonLValueExprType(SemaRef.Context)); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; @@ -1956,6 +1962,7 @@ DeclarationName InitializedEntity::getName() const { case EK_Base: case EK_ArrayElement: case EK_VectorElement: + case EK_BlockElement: return DeclarationName(); } @@ -1977,6 +1984,7 @@ DeclaratorDecl *InitializedEntity::getDecl() const { case EK_Base: case EK_ArrayElement: case EK_VectorElement: + case EK_BlockElement: return 0; } @@ -1998,6 +2006,7 @@ bool InitializedEntity::allowsNRVO() const { case EK_Base: case EK_ArrayElement: case EK_VectorElement: + case EK_BlockElement: break; } @@ -2195,7 +2204,7 @@ static void TryListInitialization(Sema &S, // FIXME: We only perform rudimentary checking of list // initializations at this point, then assume that any list // initialization of an array, aggregate, or scalar will be - // well-formed. We we actually "perform" list initialization, we'll + // well-formed. When we actually "perform" list initialization, we'll // do all of the necessary checking. C++0x initializer lists will // force us to perform more checking here. Sequence.setSequenceKind(InitializationSequence::ListInitialization); @@ -2236,8 +2245,6 @@ static void TryListInitialization(Sema &S, /// \brief Try a reference initialization that involves calling a conversion /// function. -/// -/// FIXME: look intos DRs 656, 896 static OverloadingResult TryRefInitWithConversionFunction(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, @@ -2271,11 +2278,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // The type we're converting to is a class type. Enumerate its constructors // to see if there is a suitable conversion. CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl()); - DeclarationName ConstructorName - = S.Context.DeclarationNames.getCXXConstructorName( - S.Context.getCanonicalType(T1).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = T1RecordDecl->lookup(ConstructorName); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(T1RecordDecl); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -2328,7 +2332,7 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, if (ConvTemplate) Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); else - Conv = cast<CXXConversionDecl>(*I); + Conv = cast<CXXConversionDecl>(D); // If the conversion function doesn't return a reference type, // it can't be considered for this conversion unless we're allowed to @@ -2367,13 +2371,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, // Add the user-defined conversion step. Sequence.AddUserConversionStep(Function, Best->FoundDecl, - T2.getNonReferenceType()); + T2.getNonLValueExprType(S.Context)); // Determine whether we need to perform derived-to-base or // cv-qualification adjustments. bool NewDerivedToBase = false; Sema::ReferenceCompareResult NewRefRelationship - = S.CompareReferenceRelationship(DeclLoc, T1, T2.getNonReferenceType(), + = S.CompareReferenceRelationship(DeclLoc, T1, + T2.getNonLValueExprType(S.Context), NewDerivedToBase); if (NewRefRelationship == Sema::Ref_Incompatible) { // If the type we've converted to is not reference-related to the @@ -2398,14 +2403,14 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, return OR_Success; } -/// \brief Attempt reference initialization (C++0x [dcl.init.list]) +/// \brief Attempt reference initialization (C++0x [dcl.init.ref]) static void TryReferenceInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr *Initializer, InitializationSequence &Sequence) { Sequence.setSequenceKind(InitializationSequence::ReferenceBinding); - + QualType DestType = Entity.getType(); QualType cv1T1 = DestType->getAs<ReferenceType>()->getPointeeType(); Qualifiers T1Quals; @@ -2414,7 +2419,7 @@ static void TryReferenceInitialization(Sema &S, Qualifiers T2Quals; QualType T2 = S.Context.getUnqualifiedArrayType(cv2T2, T2Quals); SourceLocation DeclLoc = Initializer->getLocStart(); - + // If the initializer is the address of an overloaded function, try // to resolve the overloaded function. If all goes well, T2 is the // type of the resulting function. @@ -2428,29 +2433,33 @@ static void TryReferenceInitialization(Sema &S, Sequence.SetFailed(InitializationSequence::FK_AddressOfOverloadFailed); return; } - + Sequence.AddAddressOverloadResolutionStep(Fn, Found); cv2T2 = Fn->getType(); T2 = cv2T2.getUnqualifiedType(); } - + // Compute some basic properties of the types and the initializer. bool isLValueRef = DestType->isLValueReferenceType(); bool isRValueRef = !isLValueRef; bool DerivedToBase = false; - Expr::isLvalueResult InitLvalue = Initializer->isLvalue(S.Context); + Expr::Classification InitCategory = Initializer->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, cv1T1, cv2T2, DerivedToBase); - + // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression of type // "cv2 T2" as follows: // // - If the reference is an lvalue reference and the initializer // expression + // Note the analogous bullet points for rvlaue refs to functions. Because + // there are no function rvalues in C++, rvalue refs to functions are treated + // like lvalue refs. OverloadingResult ConvOvlResult = OR_Success; - if (isLValueRef) { - if (InitLvalue == Expr::LV_Valid && + bool T1Function = T1->isFunctionType(); + if (isLValueRef || T1Function) { + if (InitCategory.isLValue() && RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or @@ -2478,10 +2487,13 @@ static void TryReferenceInitialization(Sema &S, // with "cv3 T3" (this conversion is selected by enumerating the // applicable conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), - if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType()) { + // If we have an rvalue ref to function type here, the rhs must be + // an rvalue. + if (RefRelationship == Sema::Ref_Incompatible && T2->isRecordType() && + (isLValueRef || InitCategory.isRValue())) { ConvOvlResult = TryRefInitWithConversionFunction(S, Entity, Kind, Initializer, - /*AllowRValues=*/false, + /*AllowRValues=*/isRValueRef, Sequence); if (ConvOvlResult == OR_Success) return; @@ -2492,19 +2504,20 @@ static void TryReferenceInitialization(Sema &S, } } } - + // - Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference // shall be an rvalue reference and the initializer expression shall - // be an rvalue. + // be an rvalue or have a function type. + // We handled the function type stuff above. if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) || - (isRValueRef && InitLvalue != Expr::LV_Valid))) { + (isRValueRef && InitCategory.isRValue()))) { if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( InitializationSequence::FK_ReferenceInitOverloadFailed, ConvOvlResult); else if (isLValueRef) - Sequence.SetFailed(InitLvalue == Expr::LV_Valid + Sequence.SetFailed(InitCategory.isLValue() ? (RefRelationship == Sema::Ref_Related ? InitializationSequence::FK_ReferenceInitDropsQualifiers : InitializationSequence::FK_NonConstLValueReferenceBindingToUnrelated) @@ -2512,15 +2525,15 @@ static void TryReferenceInitialization(Sema &S, else Sequence.SetFailed( InitializationSequence::FK_RValueReferenceBindingToLValue); - + return; } - - // - If T1 and T2 are class types and - if (T1->isRecordType() && T2->isRecordType()) { + + // - [If T1 is not a function type], if T2 is a class type and + if (!T1Function && T2->isRecordType()) { // - the initializer expression is an rvalue and "cv1 T1" is // reference-compatible with "cv2 T2", or - if (InitLvalue != Expr::LV_Valid && + if (InitCategory.isRValue() && RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { // The corresponding bullet in C++03 [dcl.init.ref]p5 gives the // compiler the freedom to perform a copy here or bind to the @@ -2543,7 +2556,7 @@ static void TryReferenceInitialization(Sema &S, Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); return; } - + // - T1 is not reference-related to T2 and the initializer expression // can be implicitly converted to an rvalue of type "cv3 T3" (this // conversion is selected by enumerating the applicable conversion @@ -2576,15 +2589,17 @@ static void TryReferenceInitialization(Sema &S, // from the initializer expression using the rules for a non-reference // copy initialization (8.5). The reference is then bound to the // temporary. [...] + // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct); - ImplicitConversionSequence ICS - = S.TryImplicitConversion(Initializer, cv1T1, - /*SuppressUserConversions=*/false, AllowExplicit, - /*FIXME:InOverloadResolution=*/false); - - if (ICS.isBad()) { + + InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + + if (S.TryImplicitConversion(Sequence, TempEntity, Initializer, + /*SuppressUserConversions*/ false, + AllowExplicit, + /*FIXME:InOverloadResolution=*/false)) { // FIXME: Use the conversion function set stored in ICS to turn // this into an overloading ambiguity diagnostic. However, we need // to keep that set as an OverloadCandidateSet rather than as some @@ -2609,8 +2624,6 @@ static void TryReferenceInitialization(Sema &S, return; } - // Perform the actual conversion. - Sequence.AddConversionSequenceStep(ICS, cv1T1); Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/true); return; } @@ -2661,11 +2674,8 @@ static void TryConstructorInitialization(Sema &S, CXXRecordDecl *DestRecordDecl = cast<CXXRecordDecl>(DestRecordType->getDecl()); - DeclarationName ConstructorName - = S.Context.DeclarationNames.getCXXConstructorName( - S.Context.getCanonicalType(DestType).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -2764,8 +2774,7 @@ static void TryValueInitialization(Sema &S, // zero-initialized and, if T’s implicitly-declared default // constructor is non-trivial, that constructor is called. if ((ClassDecl->getTagKind() == TTK_Class || - ClassDecl->getTagKind() == TTK_Struct) && - !ClassDecl->hasTrivialConstructor()) { + ClassDecl->getTagKind() == TTK_Struct)) { Sequence.AddZeroInitializationStep(Entity.getType()); return TryConstructorInitialization(S, Entity, Kind, 0, 0, T, Sequence); } @@ -2841,15 +2850,11 @@ static void TryUserDefinedConversion(Sema &S, // Try to complete the type we're converting to. if (!S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { - DeclarationName ConstructorName - = S.Context.DeclarationNames.getCXXConstructorName( - S.Context.getCanonicalType(DestType).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(DestRecordDecl); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); - bool SuppressUserConversions = false; // Find the constructor (which may be a template). CXXConstructorDecl *Constructor = 0; @@ -2858,17 +2863,8 @@ static void TryUserDefinedConversion(Sema &S, if (ConstructorTmpl) Constructor = cast<CXXConstructorDecl>( ConstructorTmpl->getTemplatedDecl()); - else { + else Constructor = cast<CXXConstructorDecl>(D); - - // If we're performing copy initialization using a copy constructor, - // we suppress user-defined conversions on the arguments. - // FIXME: Move constructors? - if (Kind.getKind() == InitializationKind::IK_Copy && - Constructor->isCopyConstructor()) - SuppressUserConversions = true; - - } if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { @@ -2876,11 +2872,11 @@ static void TryUserDefinedConversion(Sema &S, S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, &Initializer, 1, CandidateSet, - SuppressUserConversions); + /*SuppressUserConversions=*/true); else S.AddOverloadCandidate(Constructor, FoundDecl, &Initializer, 1, CandidateSet, - SuppressUserConversions); + /*SuppressUserConversions=*/true); } } } @@ -2948,7 +2944,7 @@ static void TryUserDefinedConversion(Sema &S, } // Add the user-defined conversion step that calls the conversion function. - QualType ConvType = Function->getResultType().getNonReferenceType(); + QualType ConvType = Function->getCallResultType(); if (ConvType->getAs<RecordType>()) { // If we're converting to a class type, there may be an copy if // the resulting temporary object (possible to create an object of @@ -2973,25 +2969,22 @@ static void TryUserDefinedConversion(Sema &S, } } -/// \brief Attempt an implicit conversion (C++ [conv]) converting from one -/// non-class type to another. -static void TryImplicitConversion(Sema &S, - const InitializedEntity &Entity, - const InitializationKind &Kind, - Expr *Initializer, - InitializationSequence &Sequence) { +bool Sema::TryImplicitConversion(InitializationSequence &Sequence, + const InitializedEntity &Entity, + Expr *Initializer, + bool SuppressUserConversions, + bool AllowExplicitConversions, + bool InOverloadResolution) { ImplicitConversionSequence ICS - = S.TryImplicitConversion(Initializer, Entity.getType(), - /*SuppressUserConversions=*/true, - /*AllowExplicit=*/false, - /*InOverloadResolution=*/false); - - if (ICS.isBad()) { - Sequence.SetFailed(InitializationSequence::FK_ConversionFailed); - return; - } - + = TryImplicitConversion(Initializer, Entity.getType(), + SuppressUserConversions, + AllowExplicitConversions, + InOverloadResolution); + if (ICS.isBad()) return true; + + // Perform the actual conversion. Sequence.AddConversionSequenceStep(ICS, Entity.getType()); + return false; } InitializationSequence::InitializationSequence(Sema &S, @@ -3125,8 +3118,13 @@ InitializationSequence::InitializationSequence(Sema &S, // conversions (Clause 4) will be used, if necessary, to convert the // initializer expression to the cv-unqualified version of the // destination type; no user-defined conversions are considered. - setSequenceKind(StandardConversion); - TryImplicitConversion(S, Entity, Kind, Initializer, *this); + if (S.TryImplicitConversion(*this, Entity, Initializer, + /*SuppressUserConversions*/ true, + /*AllowExplicitConversions*/ false, + /*InOverloadResolution*/ false)) + SetFailed(InitializationSequence::FK_ConversionFailed); + else + setSequenceKind(StandardConversion); } InitializationSequence::~InitializationSequence() { @@ -3168,6 +3166,7 @@ getAssignmentAction(const InitializedEntity &Entity) { case InitializedEntity::EK_Member: case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: return Sema::AA_Initializing; } @@ -3186,6 +3185,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_Base: case InitializedEntity::EK_VectorElement: case InitializedEntity::EK_Exception: + case InitializedEntity::EK_BlockElement: return false; case InitializedEntity::EK_Parameter: @@ -3205,6 +3205,7 @@ static bool shouldDestroyTemporary(const InitializedEntity &Entity) { case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: return false; case InitializedEntity::EK_Variable: @@ -3289,6 +3290,7 @@ static Sema::OwningExprResult CopyObject(Sema &S, case InitializedEntity::EK_New: case InitializedEntity::EK_Base: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_BlockElement: Loc = CurInitExpr->getLocStart(); break; } @@ -3298,12 +3300,9 @@ static Sema::OwningExprResult CopyObject(Sema &S, return move(CurInit); // Perform overload resolution using the class's copy constructors. - DeclarationName ConstructorName - = S.Context.DeclarationNames.getCXXConstructorName( - S.Context.getCanonicalType(S.Context.getTypeDeclType(Class))); DeclContext::lookup_iterator Con, ConEnd; OverloadCandidateSet CandidateSet(Loc); - for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName); + for (llvm::tie(Con, ConEnd) = S.LookupConstructors(Class); Con != ConEnd; ++Con) { // Only consider copy constructors. CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(*Con); @@ -3324,12 +3323,16 @@ static Sema::OwningExprResult CopyObject(Sema &S, break; case OR_No_Viable_Function: - S.Diag(Loc, diag::err_temp_copy_no_viable) + S.Diag(Loc, IsExtraneousCopy && !S.isSFINAEContext() + ? diag::ext_rvalue_to_reference_temp_copy_no_viable + : diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates, &CurInitExpr, 1); - return S.ExprError(); + if (!IsExtraneousCopy || S.isSFINAEContext()) + return S.ExprError(); + return move(CurInit); case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) @@ -3353,7 +3356,7 @@ static Sema::OwningExprResult CopyObject(Sema &S, CurInit.release(); // Ownership transferred into MultiExprArg, below. S.CheckConstructorAccess(Loc, Constructor, Entity, - Best->FoundDecl.getAccess()); + Best->FoundDecl.getAccess(), IsExtraneousCopy); if (IsExtraneousCopy) { // If this is a totally extraneous copy for C++03 reference @@ -3699,8 +3702,8 @@ InitializationSequence::Perform(Sema &S, CurInitExpr = static_cast<Expr *>(CurInit.get()); QualType T = CurInitExpr->getType(); if (const RecordType *Record = T->getAs<RecordType>()) { - CXXDestructorDecl *Destructor - = cast<CXXRecordDecl>(Record->getDecl())->getDestructor(S.Context); + CXXDestructorDecl *Destructor + = S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl())); S.CheckDestructorAccess(CurInitExpr->getLocStart(), Destructor, S.PDiag(diag::err_access_dtor_temp) << T); S.MarkDeclarationReferenced(CurInitExpr->getLocStart(), Destructor); @@ -3836,7 +3839,7 @@ InitializationSequence::Perform(Sema &S, } else if (Kind.getKind() == InitializationKind::IK_Value && S.getLangOptions().CPlusPlus && !Kind.isImplicitValueInit()) { - CurInit = S.Owned(new (S.Context) CXXZeroInitValueExpr(Step->Type, + CurInit = S.Owned(new (S.Context) CXXScalarValueInitExpr(Step->Type, Kind.getRange().getBegin(), Kind.getRange().getEnd())); } else { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaInit.h b/contrib/llvm/tools/clang/lib/Sema/SemaInit.h index a9064ed..44c36a7 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaInit.h +++ b/contrib/llvm/tools/clang/lib/Sema/SemaInit.h @@ -66,7 +66,10 @@ public: EK_Base, /// \brief The entity being initialized is an element of a vector. /// or vector. - EK_VectorElement + EK_VectorElement, + /// \brief The entity being initialized is a field of block descriptor for + /// the copied-in c++ object. + EK_BlockElement }; private: @@ -166,6 +169,11 @@ public: return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO); } + static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc, + QualType Type, bool NRVO) { + return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); + } + /// \brief Create the initialization entity for an exception object. static InitializedEntity InitializeException(SourceLocation ThrowLoc, QualType Type, bool NRVO) { diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp index 4555a86..2e65183 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaLookup.cpp @@ -447,11 +447,114 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) { return false; } +/// \brief Determine whether we can declare a special member function within +/// the class at this point. +static bool CanDeclareSpecialMemberFunction(ASTContext &Context, + const CXXRecordDecl *Class) { + // We need to have a definition for the class. + if (!Class->getDefinition() || Class->isDependentContext()) + return false; + + // We can't be in the middle of defining the class. + if (const RecordType *RecordTy + = Context.getTypeDeclType(Class)->getAs<RecordType>()) + return !RecordTy->isBeingDefined(); + + return false; +} + +void Sema::ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class) { + if (!CanDeclareSpecialMemberFunction(Context, Class)) + return; + + // If the default constructor has not yet been declared, do so now. + if (!Class->hasDeclaredDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + + // If the copy constructor has not yet been declared, do so now. + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + + // If the copy assignment operator has not yet been declared, do so now. + if (!Class->hasDeclaredCopyAssignment()) + DeclareImplicitCopyAssignment(Class); + + // If the destructor has not yet been declared, do so now. + if (!Class->hasDeclaredDestructor()) + DeclareImplicitDestructor(Class); +} + +/// \brief Determine whether this is the name of an implicitly-declared +/// special member function. +static bool isImplicitlyDeclaredMemberFunctionName(DeclarationName Name) { + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + case DeclarationName::CXXDestructorName: + return true; + + case DeclarationName::CXXOperatorName: + return Name.getCXXOverloadedOperator() == OO_Equal; + + default: + break; + } + + return false; +} + +/// \brief If there are any implicit member functions with the given name +/// that need to be declared in the given declaration context, do so. +static void DeclareImplicitMemberFunctionsWithName(Sema &S, + DeclarationName Name, + const DeclContext *DC) { + if (!DC) + return; + + switch (Name.getNameKind()) { + case DeclarationName::CXXConstructorName: + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && + CanDeclareSpecialMemberFunction(S.Context, Record)) { + if (!Record->hasDeclaredDefaultConstructor()) + S.DeclareImplicitDefaultConstructor( + const_cast<CXXRecordDecl *>(Record)); + if (!Record->hasDeclaredCopyConstructor()) + S.DeclareImplicitCopyConstructor(const_cast<CXXRecordDecl *>(Record)); + } + break; + + case DeclarationName::CXXDestructorName: + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && !Record->hasDeclaredDestructor() && + CanDeclareSpecialMemberFunction(S.Context, Record)) + S.DeclareImplicitDestructor(const_cast<CXXRecordDecl *>(Record)); + break; + + case DeclarationName::CXXOperatorName: + if (Name.getCXXOverloadedOperator() != OO_Equal) + break; + + if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(DC)) + if (Record->getDefinition() && !Record->hasDeclaredCopyAssignment() && + CanDeclareSpecialMemberFunction(S.Context, Record)) + S.DeclareImplicitCopyAssignment(const_cast<CXXRecordDecl *>(Record)); + break; + + default: + break; + } +} + // Adds all qualifying matches for a name within a decl context to the // given lookup result. Returns true if any matches were found. static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { bool Found = false; + // Lazily declare C++ special member functions. + if (S.getLangOptions().CPlusPlus) + DeclareImplicitMemberFunctionsWithName(S, R.getLookupName(), DC); + + // Perform lookup into this declaration context. DeclContext::lookup_const_iterator I, E; for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) { NamedDecl *D = *I; @@ -640,6 +743,17 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { DeclarationName Name = R.getLookupName(); + // If this is the name of an implicitly-declared special member function, + // go through the scope stack to implicitly declare + if (isImplicitlyDeclaredMemberFunctionName(Name)) { + for (Scope *PreS = S; PreS; PreS = PreS->getParent()) + if (DeclContext *DC = static_cast<DeclContext *>(PreS->getEntity())) + DeclareImplicitMemberFunctionsWithName(*this, Name, DC); + } + + // Implicitly declare member functions with the name we're looking for, if in + // fact we are in a scope where it matters. + Scope *Initial = S; IdentifierResolver::iterator I = IdResolver.begin(Name), @@ -1127,7 +1241,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx); - if (!LookupRec) + if (!LookupRec || !LookupRec->getDefinition()) return false; // If we're performing qualified name lookup into a dependent class, @@ -1416,11 +1530,22 @@ bool Sema::DiagnoseAmbiguousLookup(LookupResult &Result) { return true; } +namespace { + struct AssociatedLookup { + AssociatedLookup(Sema &S, + Sema::AssociatedNamespaceSet &Namespaces, + Sema::AssociatedClassSet &Classes) + : S(S), Namespaces(Namespaces), Classes(Classes) { + } + + Sema &S; + Sema::AssociatedNamespaceSet &Namespaces; + Sema::AssociatedClassSet &Classes; + }; +} + static void -addAssociatedClassesAndNamespaces(QualType T, - ASTContext &Context, - Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses); +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType T); static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, DeclContext *Ctx) { @@ -1439,10 +1564,8 @@ static void CollectEnclosingNamespace(Sema::AssociatedNamespaceSet &Namespaces, // \brief Add the associated classes and namespaces for argument-dependent // lookup that involves a template argument (C++ [basic.lookup.koenig]p2). static void -addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, - ASTContext &Context, - Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses) { +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + const TemplateArgument &Arg) { // C++ [basic.lookup.koenig]p2, last bullet: // -- [...] ; switch (Arg.getKind()) { @@ -1453,9 +1576,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, // [...] the namespaces and classes associated with the types of the // template arguments provided for template type parameters (excluding // template template parameters) - addAssociatedClassesAndNamespaces(Arg.getAsType(), Context, - AssociatedNamespaces, - AssociatedClasses); + addAssociatedClassesAndNamespaces(Result, Arg.getAsType()); break; case TemplateArgument::Template: { @@ -1467,9 +1588,9 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) { DeclContext *Ctx = ClassTemplate->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) - AssociatedClasses.insert(EnclosingClass); + Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. - CollectEnclosingNamespace(AssociatedNamespaces, Ctx); + CollectEnclosingNamespace(Result.Namespaces, Ctx); } break; } @@ -1485,9 +1606,7 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, for (TemplateArgument::pack_iterator P = Arg.pack_begin(), PEnd = Arg.pack_end(); P != PEnd; ++P) - addAssociatedClassesAndNamespaces(*P, Context, - AssociatedNamespaces, - AssociatedClasses); + addAssociatedClassesAndNamespaces(Result, *P); break; } } @@ -1496,10 +1615,13 @@ addAssociatedClassesAndNamespaces(const TemplateArgument &Arg, // argument-dependent lookup with an argument of class type // (C++ [basic.lookup.koenig]p2). static void -addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, - ASTContext &Context, - Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses) { +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, + CXXRecordDecl *Class) { + + // Just silently ignore anything whose name is __va_list_tag. + if (Class->getDeclName() == Result.S.VAListTagName) + return; + // C++ [basic.lookup.koenig]p2: // [...] // -- If T is a class type (including unions), its associated @@ -1511,13 +1633,13 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, // Add the class of which it is a member, if any. DeclContext *Ctx = Class->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) - AssociatedClasses.insert(EnclosingClass); + Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. - CollectEnclosingNamespace(AssociatedNamespaces, Ctx); + CollectEnclosingNamespace(Result.Namespaces, Ctx); // Add the class itself. If we've already seen this class, we don't // need to visit base classes. - if (!AssociatedClasses.insert(Class)) + if (!Result.Classes.insert(Class)) return; // -- If T is a template-id, its associated namespaces and classes are @@ -1533,15 +1655,13 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, = dyn_cast<ClassTemplateSpecializationDecl>(Class)) { DeclContext *Ctx = Spec->getSpecializedTemplate()->getDeclContext(); if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) - AssociatedClasses.insert(EnclosingClass); + Result.Classes.insert(EnclosingClass); // Add the associated namespace for this class. - CollectEnclosingNamespace(AssociatedNamespaces, Ctx); + CollectEnclosingNamespace(Result.Namespaces, Ctx); const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) - addAssociatedClassesAndNamespaces(TemplateArgs[I], Context, - AssociatedNamespaces, - AssociatedClasses); + addAssociatedClassesAndNamespaces(Result, TemplateArgs[I]); } // Only recurse into base classes for complete types. @@ -1573,10 +1693,10 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, if (!BaseType) continue; CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(BaseType->getDecl()); - if (AssociatedClasses.insert(BaseDecl)) { + if (Result.Classes.insert(BaseDecl)) { // Find the associated namespace for this base class. DeclContext *BaseCtx = BaseDecl->getDeclContext(); - CollectEnclosingNamespace(AssociatedNamespaces, BaseCtx); + CollectEnclosingNamespace(Result.Namespaces, BaseCtx); // Make sure we visit the bases of this base class. if (BaseDecl->bases_begin() != BaseDecl->bases_end()) @@ -1590,10 +1710,7 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, // argument-dependent lookup with an argument of type T // (C++ [basic.lookup.koenig]p2). static void -addAssociatedClassesAndNamespaces(QualType T, - ASTContext &Context, - Sema::AssociatedNamespaceSet &AssociatedNamespaces, - Sema::AssociatedClassSet &AssociatedClasses) { +addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) { // C++ [basic.lookup.koenig]p2: // // For each argument type T in the function call, there is a set @@ -1604,109 +1721,137 @@ addAssociatedClassesAndNamespaces(QualType T, // argument). Typedef names and using-declarations used to specify // the types do not contribute to this set. The sets of namespaces // and classes are determined in the following way: - T = Context.getCanonicalType(T).getUnqualifiedType(); - // -- If T is a pointer to U or an array of U, its associated - // namespaces and classes are those associated with U. - // - // We handle this by unwrapping pointer and array types immediately, - // to avoid unnecessary recursion. + llvm::SmallVector<const Type *, 16> Queue; + const Type *T = Ty->getCanonicalTypeInternal().getTypePtr(); + while (true) { - if (const PointerType *Ptr = T->getAs<PointerType>()) - T = Ptr->getPointeeType(); - else if (const ArrayType *Ptr = Context.getAsArrayType(T)) - T = Ptr->getElementType(); - else + switch (T->getTypeClass()) { + +#define TYPE(Class, Base) +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define ABSTRACT_TYPE(Class, Base) +#include "clang/AST/TypeNodes.def" + // T is canonical. We can also ignore dependent types because + // we don't need to do ADL at the definition point, but if we + // wanted to implement template export (or if we find some other + // use for associated classes and namespaces...) this would be + // wrong. break; - } - // -- If T is a fundamental type, its associated sets of - // namespaces and classes are both empty. - if (T->getAs<BuiltinType>()) - return; + // -- If T is a pointer to U or an array of U, its associated + // namespaces and classes are those associated with U. + case Type::Pointer: + T = cast<PointerType>(T)->getPointeeType().getTypePtr(); + continue; + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + T = cast<ArrayType>(T)->getElementType().getTypePtr(); + continue; - // -- If T is a class type (including unions), its associated - // classes are: the class itself; the class of which it is a - // member, if any; and its direct and indirect base - // classes. Its associated namespaces are the namespaces in - // which its associated classes are defined. - if (const RecordType *ClassType = T->getAs<RecordType>()) - if (CXXRecordDecl *ClassDecl - = dyn_cast<CXXRecordDecl>(ClassType->getDecl())) { - addAssociatedClassesAndNamespaces(ClassDecl, Context, - AssociatedNamespaces, - AssociatedClasses); - return; + // -- If T is a fundamental type, its associated sets of + // namespaces and classes are both empty. + case Type::Builtin: + break; + + // -- If T is a class type (including unions), its associated + // classes are: the class itself; the class of which it is a + // member, if any; and its direct and indirect base + // classes. Its associated namespaces are the namespaces in + // which its associated classes are defined. + case Type::Record: { + CXXRecordDecl *Class + = cast<CXXRecordDecl>(cast<RecordType>(T)->getDecl()); + addAssociatedClassesAndNamespaces(Result, Class); + break; } - // -- If T is an enumeration type, its associated namespace is - // the namespace in which it is defined. If it is class - // member, its associated class is the member’s class; else - // it has no associated class. - if (const EnumType *EnumT = T->getAs<EnumType>()) { - EnumDecl *Enum = EnumT->getDecl(); + // -- If T is an enumeration type, its associated namespace is + // the namespace in which it is defined. If it is class + // member, its associated class is the member’s class; else + // it has no associated class. + case Type::Enum: { + EnumDecl *Enum = cast<EnumType>(T)->getDecl(); - DeclContext *Ctx = Enum->getDeclContext(); - if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) - AssociatedClasses.insert(EnclosingClass); + DeclContext *Ctx = Enum->getDeclContext(); + if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx)) + Result.Classes.insert(EnclosingClass); - // Add the associated namespace for this class. - CollectEnclosingNamespace(AssociatedNamespaces, Ctx); + // Add the associated namespace for this class. + CollectEnclosingNamespace(Result.Namespaces, Ctx); - return; - } + break; + } - // -- If T is a function type, its associated namespaces and - // classes are those associated with the function parameter - // types and those associated with the return type. - if (const FunctionType *FnType = T->getAs<FunctionType>()) { - // Return type - addAssociatedClassesAndNamespaces(FnType->getResultType(), - Context, - AssociatedNamespaces, AssociatedClasses); + // -- If T is a function type, its associated namespaces and + // classes are those associated with the function parameter + // types and those associated with the return type. + case Type::FunctionProto: { + const FunctionProtoType *Proto = cast<FunctionProtoType>(T); + for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), + ArgEnd = Proto->arg_type_end(); + Arg != ArgEnd; ++Arg) + Queue.push_back(Arg->getTypePtr()); + // fallthrough + } + case Type::FunctionNoProto: { + const FunctionType *FnType = cast<FunctionType>(T); + T = FnType->getResultType().getTypePtr(); + continue; + } - const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FnType); - if (!Proto) - return; + // -- If T is a pointer to a member function of a class X, its + // associated namespaces and classes are those associated + // with the function parameter types and return type, + // together with those associated with X. + // + // -- If T is a pointer to a data member of class X, its + // associated namespaces and classes are those associated + // with the member type together with those associated with + // X. + case Type::MemberPointer: { + const MemberPointerType *MemberPtr = cast<MemberPointerType>(T); + + // Queue up the class type into which this points. + Queue.push_back(MemberPtr->getClass()); + + // And directly continue with the pointee type. + T = MemberPtr->getPointeeType().getTypePtr(); + continue; + } - // Argument types - for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), - ArgEnd = Proto->arg_type_end(); - Arg != ArgEnd; ++Arg) - addAssociatedClassesAndNamespaces(*Arg, Context, - AssociatedNamespaces, AssociatedClasses); + // As an extension, treat this like a normal pointer. + case Type::BlockPointer: + T = cast<BlockPointerType>(T)->getPointeeType().getTypePtr(); + continue; - return; - } + // References aren't covered by the standard, but that's such an + // obvious defect that we cover them anyway. + case Type::LValueReference: + case Type::RValueReference: + T = cast<ReferenceType>(T)->getPointeeType().getTypePtr(); + continue; - // -- If T is a pointer to a member function of a class X, its - // associated namespaces and classes are those associated - // with the function parameter types and return type, - // together with those associated with X. - // - // -- If T is a pointer to a data member of class X, its - // associated namespaces and classes are those associated - // with the member type together with those associated with - // X. - if (const MemberPointerType *MemberPtr = T->getAs<MemberPointerType>()) { - // Handle the type that the pointer to member points to. - addAssociatedClassesAndNamespaces(MemberPtr->getPointeeType(), - Context, - AssociatedNamespaces, - AssociatedClasses); - - // Handle the class type into which this points. - if (const RecordType *Class = MemberPtr->getClass()->getAs<RecordType>()) - addAssociatedClassesAndNamespaces(cast<CXXRecordDecl>(Class->getDecl()), - Context, - AssociatedNamespaces, - AssociatedClasses); + // These are fundamental types. + case Type::Vector: + case Type::ExtVector: + case Type::Complex: + break; - return; - } + // These are ignored by ADL. + case Type::ObjCObject: + case Type::ObjCInterface: + case Type::ObjCObjectPointer: + break; + } - // FIXME: What about block pointers? - // FIXME: What about Objective-C message sends? + if (Queue.empty()) break; + T = Queue.back(); + Queue.pop_back(); + } } /// \brief Find the associated classes and namespaces for @@ -1723,6 +1868,8 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, AssociatedNamespaces.clear(); AssociatedClasses.clear(); + AssociatedLookup Result(*this, AssociatedNamespaces, AssociatedClasses); + // C++ [basic.lookup.koenig]p2: // For each argument type T in the function call, there is a set // of zero or more associated namespaces and a set of zero or more @@ -1734,9 +1881,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, Expr *Arg = Args[ArgIdx]; if (Arg->getType() != Context.OverloadTy) { - addAssociatedClassesAndNamespaces(Arg->getType(), Context, - AssociatedNamespaces, - AssociatedClasses); + addAssociatedClassesAndNamespaces(Result, Arg->getType()); continue; } @@ -1752,17 +1897,11 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, if (unaryOp->getOpcode() == UnaryOperator::AddrOf) Arg = unaryOp->getSubExpr(); - // TODO: avoid the copies. This should be easy when the cases - // share a storage implementation. - llvm::SmallVector<NamedDecl*, 8> Functions; + UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg); + if (!ULE) continue; - if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(Arg)) - Functions.append(ULE->decls_begin(), ULE->decls_end()); - else - continue; - - for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Functions.begin(), - E = Functions.end(); I != E; ++I) { + for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end(); + I != E; ++I) { // Look through any using declarations to find the underlying function. NamedDecl *Fn = (*I)->getUnderlyingDecl(); @@ -1772,9 +1911,7 @@ Sema::FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs, // Add the classes and namespaces associated with the parameter // types and return type of this function. - addAssociatedClassesAndNamespaces(FDecl->getType(), Context, - AssociatedNamespaces, - AssociatedClasses); + addAssociatedClassesAndNamespaces(Result, FDecl->getType()); } } } @@ -1874,6 +2011,36 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, } } +/// \brief Look up the constructors for the given class. +DeclContext::lookup_result Sema::LookupConstructors(CXXRecordDecl *Class) { + // If the copy constructor has not yet been declared, do so now. + if (CanDeclareSpecialMemberFunction(Context, Class)) { + if (!Class->hasDeclaredDefaultConstructor()) + DeclareImplicitDefaultConstructor(Class); + if (!Class->hasDeclaredCopyConstructor()) + DeclareImplicitCopyConstructor(Class); + } + + CanQualType T = Context.getCanonicalType(Context.getTypeDeclType(Class)); + DeclarationName Name = Context.DeclarationNames.getCXXConstructorName(T); + return Class->lookup(Name); +} + +/// \brief Look for the destructor of the given class. +/// +/// During semantic analysis, this routine should be used in lieu of +/// CXXRecordDecl::getDestructor(). +/// +/// \returns The destructor for this class. +CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) { + // If the destructor has not yet been declared, do so now. + if (CanDeclareSpecialMemberFunction(Context, Class) && + !Class->hasDeclaredDestructor()) + DeclareImplicitDestructor(Class); + + return Class->getDestructor(); +} + void ADLResult::insert(NamedDecl *New) { NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())]; @@ -2172,6 +2339,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, if (Visited.visitedContext(Ctx->getPrimaryContext())) return; + if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx)) + Result.getSema().ForceDeclarationOfImplicitMembers(Class); + // Enumerate all of the results in this context. for (DeclContext *CurCtx = Ctx->getPrimaryContext(); CurCtx; CurCtx = CurCtx->getNextContext()) { @@ -2556,7 +2726,7 @@ DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS, bool EnteringContext, CorrectTypoContext CTC, const ObjCObjectPointerType *OPT) { - if (Diags.hasFatalErrorOccurred()) + if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking) return DeclarationName(); // Provide a stop gap for files that are just seriously broken. Trying diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp index 4c89a11..ff60599 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaObjCProperty.cpp @@ -41,7 +41,8 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_retain) && !(Attributes & ObjCDeclSpec::DQ_PR_copy))); - QualType T = GetTypeForDeclarator(FD.D, S); + TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); + QualType T = TSI->getType(); if (T->isReferenceType()) { Diag(AtLoc, diag::error_reference_property); return DeclPtrTy(); @@ -51,18 +52,22 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, cast<ObjCContainerDecl>(ClassCategory.getAs<Decl>()); if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) - if (CDecl->IsClassExtension()) - return HandlePropertyInClassExtension(S, CDecl, AtLoc, - FD, GetterSel, SetterSel, - isAssign, isReadWrite, - Attributes, - isOverridingProperty, T, - MethodImplKind); - + if (CDecl->IsClassExtension()) { + DeclPtrTy Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, + FD, GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, + isOverridingProperty, TSI, + MethodImplKind); + if (Res) + CheckObjCPropertyAttributes(Res, AtLoc, Attributes); + return Res; + } + DeclPtrTy Res = DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD, - GetterSel, SetterSel, - isAssign, isReadWrite, - Attributes, T, MethodImplKind)); + GetterSel, SetterSel, + isAssign, isReadWrite, + Attributes, TSI, MethodImplKind)); // Validate the attributes on the @property. CheckObjCPropertyAttributes(Res, AtLoc, Attributes); return Res; @@ -76,7 +81,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, const bool isReadWrite, const unsigned Attributes, bool *isOverridingProperty, - QualType T, + TypeSourceInfo *T, tok::ObjCKeywordKind MethodImplKind) { // Diagnose if this property is already in continuation class. @@ -122,6 +127,10 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, CreatePropertyDecl(S, CCPrimary, AtLoc, FD, GetterSel, SetterSel, isAssign, isReadWrite, Attributes, T, MethodImplKind, DC); + // Mark written attribute as having no attribute because + // this is not a user-written property declaration in primary + // class. + PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr); // A case of continuation class adding a new property in the class. This // is not what it was meant for. However, gcc supports it and so should we. @@ -133,7 +142,7 @@ Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, // The property 'PIDecl's readonly attribute will be over-ridden // with continuation class's readwrite property attribute! - unsigned PIkind = PIDecl->getPropertyAttributes(); + unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { unsigned retainCopyNonatomic = (ObjCPropertyDecl::OBJC_PR_retain | @@ -190,11 +199,11 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, const bool isAssign, const bool isReadWrite, const unsigned Attributes, - QualType T, + TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC){ - IdentifierInfo *PropertyId = FD.D.getIdentifier(); + QualType T = TInfo->getType(); // Issue a warning if property is 'assign' as default and its object, which is // gc'able conforms to NSCopying protocol @@ -215,7 +224,7 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, DeclContext *DC = cast<DeclContext>(CDecl); ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), - PropertyId, AtLoc, T); + PropertyId, AtLoc, TInfo); if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { @@ -265,6 +274,8 @@ ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); + PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes()); + if (MethodImplKind == tok::objc_required) PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); else if (MethodImplKind == tok::objc_optional) @@ -771,7 +782,8 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those it its super class. void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, - llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), E = IDecl->prop_end(); P != E; ++P) { @@ -781,10 +793,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, // scan through class's protocols. for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), E = IDecl->protocol_end(); PI != E; ++PI) - // Exclude property for protocols which conform to class's super-class, - // as super-class has to implement the property. - if (!ProtocolConformsToSuperClass(IDecl, (*PI))) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { if (!CATDecl->IsClassExtension()) @@ -796,20 +805,25 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, // scan through class's protocols. for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), E = CATDecl->protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = (*P); - ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; - if (!PropEntry) - PropEntry = Prop; + ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; + // Exclude property for protocols which conform to class's super-class, + // as super-class has to implement the property. + if (!PropertyFromSuper || PropertyFromSuper != Prop) { + ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; + if (!PropEntry) + PropEntry = Prop; + } } // scan through protocol's protocols. for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), E = PDecl->protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap); + CollectImmediateProperties((*PI), PropMap, SuperPropMap); } } @@ -854,33 +868,6 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, } } -/// ProtocolConformsToSuperClass - Returns true if class's given protocol -/// conforms to one of its super class's protocols. -bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, - const ObjCProtocolDecl *PDecl) { - if (const ObjCInterfaceDecl *CDecl = IDecl->getSuperClass()) { - for (ObjCInterfaceDecl::protocol_iterator PI = CDecl->protocol_begin(), - E = CDecl->protocol_end(); PI != E; ++PI) { - if (ProtocolConformsToProtocol((*PI), PDecl)) - return true; - return ProtocolConformsToSuperClass(CDecl, PDecl); - } - } - return false; -} - -bool Sema::ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, - const ObjCProtocolDecl *PDecl) { - if (PDecl->getIdentifier() == NestedProtocol->getIdentifier()) - return true; - // scan through protocol's protocols. - for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), - E = PDecl->protocol_end(); PI != E; ++PI) - if (ProtocolConformsToProtocol(NestedProtocol, (*PI))) - return true; - return false; -} - /// LookupPropertyDecl - Looks up a property in the current class and all /// its protocols. ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, @@ -943,6 +930,10 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) continue; + // Property may have been synthesized by user. + if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) + continue; + ActOnPropertyImplDecl(S, IMPDecl->getLocation(), IMPDecl->getLocation(), true, DeclPtrTy::make(IMPDecl), Prop->getIdentifier(), Prop->getIdentifier()); @@ -952,8 +943,12 @@ void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const llvm::DenseSet<Selector>& InsMap) { + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) + CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); + llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; - CollectImmediateProperties(CDecl, PropMap); + CollectImmediateProperties(CDecl, PropMap, SuperPropMap); if (PropMap.empty()) return; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 2754d44..c4ab906 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -155,7 +155,9 @@ bool StandardConversionSequence::isPointerConversionToBool() const { // check for their presence as well as checking whether FromType is // a pointer. if (getToType(1)->isBooleanType() && - (getFromType()->isPointerType() || getFromType()->isBlockPointerType() || + (getFromType()->isPointerType() || + getFromType()->isObjCObjectPointerType() || + getFromType()->isBlockPointerType() || First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) return true; @@ -498,19 +500,54 @@ void OverloadCandidateSet::clear() { // identical (return types of functions are not part of the // signature), IsOverload returns false and MatchedDecl will be set to // point to the FunctionDecl for #2. +// +// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced +// into a class by a using declaration. The rules for whether to hide +// shadow declarations ignore some properties which otherwise figure +// into a function template's signature. Sema::OverloadKind -Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old, - NamedDecl *&Match) { +Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, + NamedDecl *&Match, bool NewIsUsingDecl) { for (LookupResult::iterator I = Old.begin(), E = Old.end(); I != E; ++I) { - NamedDecl *OldD = (*I)->getUnderlyingDecl(); + NamedDecl *OldD = *I; + + bool OldIsUsingDecl = false; + if (isa<UsingShadowDecl>(OldD)) { + OldIsUsingDecl = true; + + // We can always introduce two using declarations into the same + // context, even if they have identical signatures. + if (NewIsUsingDecl) continue; + + OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl(); + } + + // If either declaration was introduced by a using declaration, + // we'll need to use slightly different rules for matching. + // Essentially, these rules are the normal rules, except that + // function templates hide function templates with different + // return types or template parameter lists. + bool UseMemberUsingDeclRules = + (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord(); + if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) { - if (!IsOverload(New, OldT->getTemplatedDecl())) { + if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); + continue; + } + Match = *I; return Ovl_Match; } } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) { - if (!IsOverload(New, OldF)) { + if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { + if (UseMemberUsingDeclRules && OldIsUsingDecl) { + HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); + continue; + } + Match = *I; return Ovl_Match; } @@ -534,7 +571,8 @@ Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old, return Ovl_Overload; } -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) { +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, + bool UseUsingDeclRules) { FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate(); FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); @@ -579,7 +617,10 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) { // // We check the return type and template parameter lists for function // templates first; the remaining checks follow. - if (NewTemplate && + // + // However, we don't consider either of these when deciding whether + // a member introduced by a shadow declaration is hidden. + if (!UseUsingDeclRules && NewTemplate && (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch) || @@ -804,7 +845,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, return false; // Vector splat from any arithmetic type to a vector. - if (!FromType->isVectorType() && FromType->isArithmeticType()) { + if (FromType->isArithmeticType()) { ICK = ICK_Vector_Splat; return true; } @@ -960,8 +1001,8 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // Complex promotion (Clang extension) SCS.Second = ICK_Complex_Promotion; FromType = ToType.getUnqualifiedType(); - } else if ((FromType->isIntegralType() || FromType->isEnumeralType()) && - (ToType->isIntegralType() && !ToType->isEnumeralType())) { + } else if (FromType->isIntegralOrEnumerationType() && + ToType->isIntegralType(Context)) { // Integral conversions (C++ 4.7). SCS.Second = ICK_Integral_Conversion; FromType = ToType.getUnqualifiedType(); @@ -974,15 +1015,14 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // Complex-real conversions (C99 6.3.1.7) SCS.Second = ICK_Complex_Real; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isFloatingType() && ToType->isFloatingType()) { + } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { // Floating point conversions (C++ 4.8). SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); - } else if ((FromType->isFloatingType() && - ToType->isIntegralType() && (!ToType->isBooleanType() && - !ToType->isEnumeralType())) || - ((FromType->isIntegralType() || FromType->isEnumeralType()) && - ToType->isFloatingType())) { + } else if ((FromType->isRealFloatingType() && + ToType->isIntegralType(Context) && !ToType->isBooleanType()) || + (FromType->isIntegralOrEnumerationType() && + ToType->isRealFloatingType())) { // Floating-integral conversions (C++ 4.9). SCS.Second = ICK_Floating_Integral; FromType = ToType.getUnqualifiedType(); @@ -1141,7 +1181,7 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { if (From) if (FieldDecl *MemberDecl = From->getBitField()) { APSInt BitWidth; - if (FromType->isIntegralType() && !FromType->isEnumeralType() && + if (FromType->isIntegralType(Context) && MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); ToSize = Context.getTypeSize(ToType); @@ -1271,7 +1311,7 @@ static bool isNullPointerConstantForConversion(Expr *Expr, // Handle value-dependent integral null pointer constants correctly. // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 if (Expr->isValueDependent() && !Expr->isTypeDependent() && - Expr->getType()->isIntegralType()) + Expr->getType()->isIntegerType() && !Expr->getType()->isEnumeralType()) return !InOverloadResolution; return Expr->isNullPointerConstant(Context, @@ -1622,6 +1662,12 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, bool IgnoreBaseAccess) { QualType FromType = From->getType(); + if (CXXBoolLiteralExpr* LitBool + = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens())) + if (LitBool->getValue() == false) + Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false) + << ToType; + if (const PointerType *FromPtrType = FromType->getAs<PointerType>()) if (const PointerType *ToPtrType = ToType->getAs<PointerType>()) { QualType FromPointeeType = FromPtrType->getPointeeType(), @@ -1779,7 +1825,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { // in multi-level pointers, subject to the following rules: [...] bool PreviousToQualsIncludeConst = true; bool UnwrappedAnyPointer = false; - while (UnwrapSimilarPointerTypes(FromType, ToType)) { + while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -1850,12 +1896,8 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { - DeclarationName ConstructorName - = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ToType).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) - = ToRecordDecl->lookup(ConstructorName); + for (llvm::tie(Con, ConEnd) = LookupConstructors(ToRecordDecl); Con != ConEnd; ++Con) { NamedDecl *D = *Con; DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess()); @@ -2067,6 +2109,16 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, return ImplicitConversionSequence::Indistinguishable; } +static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { + while (Context.UnwrapSimilarPointerTypes(T1, T2)) { + Qualifiers Quals; + T1 = Context.getUnqualifiedArrayType(T1, Quals); + T2 = Context.getUnqualifiedArrayType(T2, Quals); + } + + return Context.hasSameUnqualifiedType(T1, T2); +} + // Per 13.3.3.2p3, compare the given standard conversion sequences to // determine if one is a proper subset of the other. static ImplicitConversionSequence::CompareKind @@ -2092,7 +2144,7 @@ compareStandardConversionSubsets(ASTContext &Context, Result = ImplicitConversionSequence::Worse; else return ImplicitConversionSequence::Indistinguishable; - } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1))) + } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1))) return ImplicitConversionSequence::Indistinguishable; if (SCS1.Third == SCS2.Third) { @@ -2299,7 +2351,7 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, ImplicitConversionSequence::CompareKind Result = ImplicitConversionSequence::Indistinguishable; - while (UnwrapSimilarPointerTypes(T1, T2)) { + while (Context.UnwrapSimilarPointerTypes(T1, T2)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -2566,6 +2618,95 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, return Ref_Related; } +/// \brief Look for a user-defined conversion to an lvalue reference-compatible +/// with DeclType. Return true if something definite is found. +static bool +FindConversionToLValue(Sema &S, ImplicitConversionSequence &ICS, + QualType DeclType, SourceLocation DeclLoc, + Expr *Init, QualType T2, bool AllowExplicit) { + assert(T2->isRecordType() && "Can only find conversions of record types."); + CXXRecordDecl *T2RecordDecl + = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); + + OverloadCandidateSet CandidateSet(DeclLoc); + const UnresolvedSetImpl *Conversions + = T2RecordDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = *I; + CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + FunctionTemplateDecl *ConvTemplate + = dyn_cast<FunctionTemplateDecl>(D); + CXXConversionDecl *Conv; + if (ConvTemplate) + Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); + else + Conv = cast<CXXConversionDecl>(D); + + // If the conversion function doesn't return a reference type, + // it can't be considered for this conversion. An rvalue reference + // is only acceptable if its referencee is a function type. + const ReferenceType *RefType = + Conv->getConversionType()->getAs<ReferenceType>(); + if (RefType && (RefType->isLValueReferenceType() || + RefType->getPointeeType()->isFunctionType()) && + (AllowExplicit || !Conv->isExplicit())) { + if (ConvTemplate) + S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, + Init, DeclType, CandidateSet); + else + S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, + DeclType, CandidateSet); + } + } + + OverloadCandidateSet::iterator Best; + switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) { + case OR_Success: + // C++ [over.ics.ref]p1: + // + // [...] If the parameter binds directly to the result of + // applying a conversion function to the argument + // expression, the implicit conversion sequence is a + // user-defined conversion sequence (13.3.3.1.2), with the + // second standard conversion sequence either an identity + // conversion or, if the conversion function returns an + // entity of a type that is a derived class of the parameter + // type, a derived-to-base Conversion. + if (!Best->FinalConversion.DirectBinding) + return false; + + ICS.setUserDefined(); + ICS.UserDefined.Before = Best->Conversions[0].Standard; + ICS.UserDefined.After = Best->FinalConversion; + ICS.UserDefined.ConversionFunction = Best->Function; + ICS.UserDefined.EllipsisConversion = false; + assert(ICS.UserDefined.After.ReferenceBinding && + ICS.UserDefined.After.DirectBinding && + "Expected a direct reference binding!"); + return true; + + case OR_Ambiguous: + ICS.setAmbiguous(); + for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); + Cand != CandidateSet.end(); ++Cand) + if (Cand->Viable) + ICS.Ambiguous.addConversion(Cand->Function); + return true; + + case OR_No_Viable_Function: + case OR_Deleted: + // There was no suitable conversion, or we found a deleted + // conversion; continue with other checks. + return false; + } + + return false; +} + /// \brief Compute an implicit conversion sequence for reference /// initialization. static ImplicitConversionSequence @@ -2595,149 +2736,72 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // Compute some basic properties of the types and the initializer. bool isRValRef = DeclType->isRValueReferenceType(); bool DerivedToBase = false; - Expr::isLvalueResult InitLvalue = Init->isLvalue(S.Context); + Expr::Classification InitCategory = Init->Classify(S.Context); Sema::ReferenceCompareResult RefRelationship = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase); - // C++ [over.ics.ref]p3: - // Except for an implicit object parameter, for which see 13.3.1, - // a standard conversion sequence cannot be formed if it requires - // binding an lvalue reference to non-const to an rvalue or - // binding an rvalue reference to an lvalue. - // - // FIXME: DPG doesn't trust this code. It seems far too early to - // abort because of a binding of an rvalue reference to an lvalue. - if (isRValRef && InitLvalue == Expr::LV_Valid) - return ICS; - - // C++0x [dcl.init.ref]p16: + // C++0x [dcl.init.ref]p5: // A reference to type "cv1 T1" is initialized by an expression // of type "cv2 T2" as follows: - // -- If the initializer expression - // -- is an lvalue (but is not a bit-field), and "cv1 T1" is - // reference-compatible with "cv2 T2," or - // - // Per C++ [over.ics.ref]p4, we don't check the bit-field property here. - if (InitLvalue == Expr::LV_Valid && - RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { - // C++ [over.ics.ref]p1: - // When a parameter of reference type binds directly (8.5.3) - // to an argument expression, the implicit conversion sequence - // is the identity conversion, unless the argument expression - // has a type that is a derived class of the parameter type, - // in which case the implicit conversion sequence is a - // derived-to-base Conversion (13.3.3.1). - ICS.setStandard(); - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS.Standard.setToType(0, T2); - ICS.Standard.setToType(1, T1); - ICS.Standard.setToType(2, T1); - ICS.Standard.ReferenceBinding = true; - ICS.Standard.DirectBinding = true; - ICS.Standard.RRefBinding = false; - ICS.Standard.CopyConstructor = 0; - - // Nothing more to do: the inaccessibility/ambiguity check for - // derived-to-base conversions is suppressed when we're - // computing the implicit conversion sequence (C++ - // [over.best.ics]p2). - return ICS; - } - - // -- has a class type (i.e., T2 is a class type), where T1 is - // not reference-related to T2, and can be implicitly - // converted to an lvalue of type "cv3 T3," where "cv1 T1" - // is reference-compatible with "cv3 T3" 92) (this - // conversion is selected by enumerating the applicable - // conversion functions (13.3.1.6) and choosing the best - // one through overload resolution (13.3)), - if (!isRValRef && !SuppressUserConversions && T2->isRecordType() && - !S.RequireCompleteType(DeclLoc, T2, 0) && - RefRelationship == Sema::Ref_Incompatible) { - CXXRecordDecl *T2RecordDecl - = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); - - OverloadCandidateSet CandidateSet(DeclLoc); - const UnresolvedSetImpl *Conversions - = T2RecordDecl->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { - NamedDecl *D = *I; - CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext()); - if (isa<UsingShadowDecl>(D)) - D = cast<UsingShadowDecl>(D)->getTargetDecl(); - - FunctionTemplateDecl *ConvTemplate - = dyn_cast<FunctionTemplateDecl>(D); - CXXConversionDecl *Conv; - if (ConvTemplate) - Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl()); - else - Conv = cast<CXXConversionDecl>(D); - - // If the conversion function doesn't return a reference type, - // it can't be considered for this conversion. - if (Conv->getConversionType()->isLValueReferenceType() && - (AllowExplicit || !Conv->isExplicit())) { - if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, DeclType, CandidateSet); - else - S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - DeclType, CandidateSet); - } - } - - OverloadCandidateSet::iterator Best; - switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) { - case OR_Success: + // -- If reference is an lvalue reference and the initializer expression + // The next bullet point (T1 is a function) is pretty much equivalent to this + // one, so it's handled here. + if (!isRValRef || T1->isFunctionType()) { + // -- is an lvalue (but is not a bit-field), and "cv1 T1" is + // reference-compatible with "cv2 T2," or + // + // Per C++ [over.ics.ref]p4, we don't check the bit-field property here. + if (InitCategory.isLValue() && + RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { // C++ [over.ics.ref]p1: - // - // [...] If the parameter binds directly to the result of - // applying a conversion function to the argument - // expression, the implicit conversion sequence is a - // user-defined conversion sequence (13.3.3.1.2), with the - // second standard conversion sequence either an identity - // conversion or, if the conversion function returns an - // entity of a type that is a derived class of the parameter - // type, a derived-to-base Conversion. - if (!Best->FinalConversion.DirectBinding) - break; - - ICS.setUserDefined(); - ICS.UserDefined.Before = Best->Conversions[0].Standard; - ICS.UserDefined.After = Best->FinalConversion; - ICS.UserDefined.ConversionFunction = Best->Function; - ICS.UserDefined.EllipsisConversion = false; - assert(ICS.UserDefined.After.ReferenceBinding && - ICS.UserDefined.After.DirectBinding && - "Expected a direct reference binding!"); - return ICS; - - case OR_Ambiguous: - ICS.setAmbiguous(); - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); - Cand != CandidateSet.end(); ++Cand) - if (Cand->Viable) - ICS.Ambiguous.addConversion(Cand->Function); + // When a parameter of reference type binds directly (8.5.3) + // to an argument expression, the implicit conversion sequence + // is the identity conversion, unless the argument expression + // has a type that is a derived class of the parameter type, + // in which case the implicit conversion sequence is a + // derived-to-base Conversion (13.3.3.1). + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + ICS.Standard.DirectBinding = true; + ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.CopyConstructor = 0; + + // Nothing more to do: the inaccessibility/ambiguity check for + // derived-to-base conversions is suppressed when we're + // computing the implicit conversion sequence (C++ + // [over.best.ics]p2). return ICS; + } - case OR_No_Viable_Function: - case OR_Deleted: - // There was no suitable conversion, or we found a deleted - // conversion; continue with other checks. - break; + // -- has a class type (i.e., T2 is a class type), where T1 is + // not reference-related to T2, and can be implicitly + // converted to an lvalue of type "cv3 T3," where "cv1 T1" + // is reference-compatible with "cv3 T3" 92) (this + // conversion is selected by enumerating the applicable + // conversion functions (13.3.1.6) and choosing the best + // one through overload resolution (13.3)), + if (!SuppressUserConversions && T2->isRecordType() && + !S.RequireCompleteType(DeclLoc, T2, 0) && + RefRelationship == Sema::Ref_Incompatible) { + if (FindConversionToLValue(S, ICS, DeclType, DeclLoc, + Init, T2, AllowExplicit)) + return ICS; } } - // -- Otherwise, the reference shall be to a non-volatile const - // type (i.e., cv1 shall be const), or the reference shall be an - // rvalue reference and the initializer expression shall be an rvalue. + // -- Otherwise, the reference shall be an lvalue reference to a + // non-volatile const type (i.e., cv1 shall be const), or the reference + // shall be an rvalue reference and the initializer expression shall be + // an rvalue or have a function type. // // We actually handle one oddity of C++ [over.ics.ref] at this // point, which is that, due to p2 (which short-circuits reference @@ -2746,10 +2810,26 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // reference to bind to an rvalue. Hence the check for the presence // of "const" rather than checking for "const" being the only // qualifier. - if (!isRValRef && !T1.isConstQualified()) + // This is also the point where rvalue references and lvalue inits no longer + // go together. + if ((!isRValRef && !T1.isConstQualified()) || + (isRValRef && InitCategory.isLValue())) + return ICS; + + // -- If T1 is a function type, then + // -- if T2 is the same type as T1, the reference is bound to the + // initializer expression lvalue; + // -- if T2 is a class type and the initializer expression can be + // implicitly converted to an lvalue of type T1 [...], the + // reference is bound to the function lvalue that is the result + // of the conversion; + // This is the same as for the lvalue case above, so it was handled there. + // -- otherwise, the program is ill-formed. + // This is the one difference to the lvalue case. + if (T1->isFunctionType()) return ICS; - // -- if T2 is a class type and + // -- Otherwise, if T2 is a class type and // -- the initializer expression is an rvalue and "cv1 T1" // is reference-compatible with "cv2 T2," or // @@ -2768,7 +2848,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // // We're only checking the first case here, which is a direct // binding in C++0x but not in C++03. - if (InitLvalue != Expr::LV_Valid && T2->isRecordType() && + if (InitCategory.isRValue() && T2->isRecordType() && RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { ICS.setStandard(); ICS.Standard.First = ICK_Identity; @@ -3012,6 +3092,177 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { return true; } +/// \brief Attempt to convert the given expression to an integral or +/// enumeration type. +/// +/// This routine will attempt to convert an expression of class type to an +/// integral or enumeration type, if that class type only has a single +/// conversion to an integral or enumeration type. +/// +/// \param Loc The source location of the construct that requires the +/// conversion. +/// +/// \param FromE The expression we're converting from. +/// +/// \param NotIntDiag The diagnostic to be emitted if the expression does not +/// have integral or enumeration type. +/// +/// \param IncompleteDiag The diagnostic to be emitted if the expression has +/// incomplete class type. +/// +/// \param ExplicitConvDiag The diagnostic to be emitted if we're calling an +/// explicit conversion function (because no implicit conversion functions +/// were available). This is a recovery mode. +/// +/// \param ExplicitConvNote The note to be emitted with \p ExplicitConvDiag, +/// showing which conversion was picked. +/// +/// \param AmbigDiag The diagnostic to be emitted if there is more than one +/// conversion function that could convert to integral or enumeration type. +/// +/// \param AmbigNote The note to be emitted with \p AmbigDiag for each +/// usable conversion function. +/// +/// \param ConvDiag The diagnostic to be emitted if we are calling a conversion +/// function, which may be an extension in this case. +/// +/// \returns The expression, converted to an integral or enumeration type if +/// successful. +Sema::OwningExprResult +Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, ExprArg FromE, + const PartialDiagnostic &NotIntDiag, + const PartialDiagnostic &IncompleteDiag, + const PartialDiagnostic &ExplicitConvDiag, + const PartialDiagnostic &ExplicitConvNote, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &AmbigNote, + const PartialDiagnostic &ConvDiag) { + Expr *From = static_cast<Expr *>(FromE.get()); + + // We can't perform any more checking for type-dependent expressions. + if (From->isTypeDependent()) + return move(FromE); + + // If the expression already has integral or enumeration type, we're golden. + QualType T = From->getType(); + if (T->isIntegralOrEnumerationType()) + return move(FromE); + + // FIXME: Check for missing '()' if T is a function type? + + // If we don't have a class type in C++, there's no way we can get an + // expression of integral or enumeration type. + const RecordType *RecordTy = T->getAs<RecordType>(); + if (!RecordTy || !getLangOptions().CPlusPlus) { + Diag(Loc, NotIntDiag) + << T << From->getSourceRange(); + return move(FromE); + } + + // We must have a complete class type. + if (RequireCompleteType(Loc, T, IncompleteDiag)) + return move(FromE); + + // Look for a conversion to an integral or enumeration type. + UnresolvedSet<4> ViableConversions; + UnresolvedSet<4> ExplicitConversions; + const UnresolvedSetImpl *Conversions + = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); + + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); + I != E; + ++I) { + if (CXXConversionDecl *Conversion + = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) + if (Conversion->getConversionType().getNonReferenceType() + ->isIntegralOrEnumerationType()) { + if (Conversion->isExplicit()) + ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); + else + ViableConversions.addDecl(I.getDecl(), I.getAccess()); + } + } + + switch (ViableConversions.size()) { + case 0: + if (ExplicitConversions.size() == 1) { + DeclAccessPair Found = ExplicitConversions[0]; + CXXConversionDecl *Conversion + = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + + // The user probably meant to invoke the given explicit + // conversion; use it. + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + std::string TypeStr; + ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy); + + Diag(Loc, ExplicitConvDiag) + << T << ConvTy + << FixItHint::CreateInsertion(From->getLocStart(), + "static_cast<" + TypeStr + ">(") + << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()), + ")"); + Diag(Conversion->getLocation(), ExplicitConvNote) + << ConvTy->isEnumeralType() << ConvTy; + + // If we aren't in a SFINAE context, build a call to the + // explicit conversion function. + if (isSFINAEContext()) + return ExprError(); + + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found, Conversion); + FromE = Owned(From); + } + + // We'll complain below about a non-integral condition type. + break; + + case 1: { + // Apply this conversion. + DeclAccessPair Found = ViableConversions[0]; + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); + + CXXConversionDecl *Conversion + = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); + QualType ConvTy + = Conversion->getConversionType().getNonReferenceType(); + if (ConvDiag.getDiagID()) { + if (isSFINAEContext()) + return ExprError(); + + Diag(Loc, ConvDiag) + << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); + } + + From = BuildCXXMemberCallExpr(FromE.takeAs<Expr>(), Found, + cast<CXXConversionDecl>(Found->getUnderlyingDecl())); + FromE = Owned(From); + break; + } + + default: + Diag(Loc, AmbigDiag) + << T << From->getSourceRange(); + for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { + CXXConversionDecl *Conv + = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); + QualType ConvTy = Conv->getConversionType().getNonReferenceType(); + Diag(Conv->getLocation(), AmbigNote) + << ConvTy->isEnumeralType() << ConvTy; + } + return move(FromE); + } + + if (!From->getType()->isIntegralOrEnumerationType()) + Diag(Loc, NotIntDiag) + << From->getType() << From->getSourceRange(); + + return move(FromE); +} + /// AddOverloadCandidate - Adds the given function to the set of /// candidate functions, using the given function call arguments. If /// @p SuppressUserConversions, then don't allow user-defined @@ -3476,7 +3727,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // there are 0 arguments (i.e., nothing is allocated using ASTContext's // allocator). CallExpr Call(Context, &ConversionFn, 0, 0, - Conversion->getConversionType().getNonReferenceType(), + Conversion->getConversionType().getNonLValueExprType(Context), From->getLocStart()); ImplicitConversionSequence ICS = TryCopyInitialization(*this, &Call, ToType, @@ -4949,7 +5200,7 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, // - F1 is a non-template function and F2 is a function template // specialization, or, if not that, - if (Cand1.Function && !Cand1.Function->getPrimaryTemplate() && + if ((!Cand1.Function || !Cand1.Function->getPrimaryTemplate()) && Cand2.Function && Cand2.Function->getPrimaryTemplate()) return true; @@ -5230,6 +5481,46 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { return; } + // Diagnose base -> derived pointer conversions. + unsigned BaseToDerivedConversion = 0; + if (const PointerType *FromPtrTy = FromTy->getAs<PointerType>()) { + if (const PointerType *ToPtrTy = ToTy->getAs<PointerType>()) { + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + !FromPtrTy->getPointeeType()->isIncompleteType() && + !ToPtrTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToPtrTy->getPointeeType(), + FromPtrTy->getPointeeType())) + BaseToDerivedConversion = 1; + } + } else if (const ObjCObjectPointerType *FromPtrTy + = FromTy->getAs<ObjCObjectPointerType>()) { + if (const ObjCObjectPointerType *ToPtrTy + = ToTy->getAs<ObjCObjectPointerType>()) + if (const ObjCInterfaceDecl *FromIface = FromPtrTy->getInterfaceDecl()) + if (const ObjCInterfaceDecl *ToIface = ToPtrTy->getInterfaceDecl()) + if (ToPtrTy->getPointeeType().isAtLeastAsQualifiedAs( + FromPtrTy->getPointeeType()) && + FromIface->isSuperClassOf(ToIface)) + BaseToDerivedConversion = 2; + } else if (const ReferenceType *ToRefTy = ToTy->getAs<ReferenceType>()) { + if (ToRefTy->getPointeeType().isAtLeastAsQualifiedAs(FromTy) && + !FromTy->isIncompleteType() && + !ToRefTy->getPointeeType()->isIncompleteType() && + S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) + BaseToDerivedConversion = 3; + } + + if (BaseToDerivedConversion) { + S.Diag(Fn->getLocation(), + diag::note_ovl_candidate_bad_base_to_derived_conv) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << (BaseToDerivedConversion - 1) + << FromTy << ToTy << I+1; + return; + } + // TODO: specialize more based on the kind of mismatch S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv) << (unsigned) FnKind << FnDesc @@ -5673,7 +5964,10 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, Cands.push_back(Cand); else if (OCD == OCD_AllCandidates) { CompleteNonViableCandidate(*this, Cand, Args, NumArgs); - Cands.push_back(Cand); + if (Cand->Function || Cand->IsSurrogate) + Cands.push_back(Cand); + // Otherwise, this a non-viable builtin candidate. We do not, in general, + // want to list every possible builtin candidate. } } @@ -5683,17 +5977,26 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, bool ReportedAmbiguousConversions = false; llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E; + const Diagnostic::OverloadsShown ShowOverloads = Diags.getShowOverloads(); + unsigned CandsShown = 0; for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { OverloadCandidate *Cand = *I; + // Set an arbitrary limit on the number of candidate functions we'll spam + // the user with. FIXME: This limit should depend on details of the + // candidate list. + if (CandsShown >= 4 && ShowOverloads == Diagnostic::Ovl_Best) { + break; + } + ++CandsShown; + if (Cand->Function) NoteFunctionCandidate(*this, Cand, Args, NumArgs); else if (Cand->IsSurrogate) NoteSurrogateCandidate(*this, Cand); - - // This a builtin candidate. We do not, in general, want to list - // every possible builtin candidate. - else if (Cand->Viable) { + else { + assert(Cand->Viable && + "Non-viable built-in candidates are not added to Cands."); // Generally we only see ambiguities including viable builtin // operators if overload resolution got screwed up by an // ambiguous user-defined conversion. @@ -5709,6 +6012,9 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand); } } + + if (I != E) + Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); } static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) { @@ -5981,7 +6287,8 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { // specified and it, along with any default template arguments, // identifies a single function template specialization, then the // template-id is an lvalue for the function template specialization. - FunctionTemplateDecl *FunctionTemplate = cast<FunctionTemplateDecl>(*I); + FunctionTemplateDecl *FunctionTemplate + = cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()); // C++ [over.over]p2: // If the name is a function template, template argument deduction is @@ -6159,7 +6466,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, Sema::MultiExprArg(SemaRef, (void**) Args, NumArgs), CommaLocs, RParenLoc); } - + /// ResolveOverloadedCallFn - Given the call expression that calls Fn /// (which eventually refers to the declaration Func) and the call /// arguments Args/NumArgs, attempt to resolve the function call down @@ -6290,6 +6597,12 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, } if (Input->isTypeDependent()) { + if (Fns.empty()) + return Owned(new (Context) UnaryOperator(input.takeAs<Expr>(), + Opc, + Context.DependentTy, + OpLoc)); + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, @@ -6356,7 +6669,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); // Determine the result type - QualType ResultTy = FnDecl->getResultType().getNonReferenceType(); + QualType ResultTy = FnDecl->getCallResultType(); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -6563,8 +6876,8 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Determine the result type QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + = FnDecl->getType()->getAs<FunctionType>() + ->getCallResultType(Context); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -6720,8 +7033,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Determine the result type QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>()->getResultType(); - ResultTy = ResultTy.getNonReferenceType(); + = FnDecl->getType()->getAs<FunctionType>() + ->getCallResultType(Context); // Build the actual expression node. Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), @@ -6909,7 +7222,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, ExprOwningPtr<CXXMemberCallExpr> TheCall(this, new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, - Method->getResultType().getNonReferenceType(), + Method->getCallResultType(), RParenLoc)); // Check for a valid return type. @@ -7124,7 +7437,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // Once we've built TheCall, all of the expressions are properly // owned. - QualType ResultTy = Method->getResultType().getNonReferenceType(); + QualType ResultTy = Method->getCallResultType(); ExprOwningPtr<CXXOperatorCallExpr> TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, MethodArgs, NumArgs + 1, @@ -7280,7 +7593,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { SourceLocation()); UsualUnaryConversions(FnExpr); - QualType ResultTy = Method->getResultType().getNonReferenceType(); + QualType ResultTy = Method->getCallResultType(); ExprOwningPtr<CXXOperatorCallExpr> TheCall(this, new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, &Base, 1, ResultTy, OpLoc)); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp index 875b160..9c8f48b 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaStmt.cpp @@ -92,12 +92,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (const CXXExprWithTemporaries *Temps = dyn_cast<CXXExprWithTemporaries>(E)) E = Temps->getSubExpr(); - if (const CXXZeroInitValueExpr *Zero = dyn_cast<CXXZeroInitValueExpr>(E)) { - if (const RecordType *RecordT = Zero->getType()->getAs<RecordType>()) - if (CXXRecordDecl *RecordD = dyn_cast<CXXRecordDecl>(RecordT->getDecl())) - if (!RecordD->hasTrivialDestructor()) - return; - } if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { if (E->getType()->isVoidType()) @@ -304,7 +298,7 @@ Sema::ActOnIfStmt(SourceLocation IfLoc, FullExprArg CondVal, DeclPtrTy CondVar, DiagnoseUnusedExprResult(elseStmt); CondResult.release(); - return Owned(new (Context) IfStmt(IfLoc, ConditionVar, ConditionExpr, + return Owned(new (Context) IfStmt(Context, IfLoc, ConditionVar, ConditionExpr, thenStmt, ElseLoc, elseStmt)); } @@ -400,124 +394,16 @@ static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { - const ImplicitCastExpr *ImplicitCast = - dyn_cast_or_null<ImplicitCastExpr>(expr); - if (ImplicitCast != NULL) { + if (const CastExpr *ImplicitCast = dyn_cast<ImplicitCastExpr>(expr)) { const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr(); QualType TypeBeforePromotion = ExprBeforePromotion->getType(); - if (TypeBeforePromotion->isIntegralType()) { + if (TypeBeforePromotion->isIntegralOrEnumerationType()) { return TypeBeforePromotion; } } return expr->getType(); } -/// \brief Check (and possibly convert) the condition in a switch -/// statement in C++. -static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, - Expr *&CondExpr) { - if (CondExpr->isTypeDependent()) - return false; - - QualType CondType = CondExpr->getType(); - - // C++ 6.4.2.p2: - // The condition shall be of integral type, enumeration type, or of a class - // type for which a single conversion function to integral or enumeration - // type exists (12.3). If the condition is of class type, the condition is - // converted by calling that conversion function, and the result of the - // conversion is used in place of the original condition for the remainder - // of this section. Integral promotions are performed. - - // Make sure that the condition expression has a complete type, - // otherwise we'll never find any conversions. - if (S.RequireCompleteType(SwitchLoc, CondType, - S.PDiag(diag::err_switch_incomplete_class_type) - << CondExpr->getSourceRange())) - return true; - - UnresolvedSet<4> ViableConversions; - UnresolvedSet<4> ExplicitConversions; - if (const RecordType *RecordTy = CondType->getAs<RecordType>()) { - const UnresolvedSetImpl *Conversions - = cast<CXXRecordDecl>(RecordTy->getDecl()) - ->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { - if (CXXConversionDecl *Conversion - = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) - if (Conversion->getConversionType().getNonReferenceType() - ->isIntegralType()) { - if (Conversion->isExplicit()) - ExplicitConversions.addDecl(I.getDecl(), I.getAccess()); - else - ViableConversions.addDecl(I.getDecl(), I.getAccess()); - } - } - - switch (ViableConversions.size()) { - case 0: - if (ExplicitConversions.size() == 1) { - DeclAccessPair Found = ExplicitConversions[0]; - CXXConversionDecl *Conversion = - cast<CXXConversionDecl>(Found->getUnderlyingDecl()); - // The user probably meant to invoke the given explicit - // conversion; use it. - QualType ConvTy - = Conversion->getConversionType().getNonReferenceType(); - std::string TypeStr; - ConvTy.getAsStringInternal(TypeStr, S.Context.PrintingPolicy); - - S.Diag(SwitchLoc, diag::err_switch_explicit_conversion) - << CondType << ConvTy << CondExpr->getSourceRange() - << FixItHint::CreateInsertion(CondExpr->getLocStart(), - "static_cast<" + TypeStr + ">(") - << FixItHint::CreateInsertion( - S.PP.getLocForEndOfToken(CondExpr->getLocEnd()), - ")"); - S.Diag(Conversion->getLocation(), diag::note_switch_conversion) - << ConvTy->isEnumeralType() << ConvTy; - - // If we aren't in a SFINAE context, build a call to the - // explicit conversion function. - if (S.isSFINAEContext()) - return true; - - S.CheckMemberOperatorAccess(CondExpr->getExprLoc(), - CondExpr, 0, Found); - CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, Conversion); - } - - // We'll complain below about a non-integral condition type. - break; - - case 1: { - // Apply this conversion. - DeclAccessPair Found = ViableConversions[0]; - S.CheckMemberOperatorAccess(CondExpr->getExprLoc(), - CondExpr, 0, Found); - CondExpr = S.BuildCXXMemberCallExpr(CondExpr, Found, - cast<CXXConversionDecl>(Found->getUnderlyingDecl())); - break; - } - - default: - S.Diag(SwitchLoc, diag::err_switch_multiple_conversions) - << CondType << CondExpr->getSourceRange(); - for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) { - CXXConversionDecl *Conv - = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl()); - QualType ConvTy = Conv->getConversionType().getNonReferenceType(); - S.Diag(Conv->getLocation(), diag::note_switch_conversion) - << ConvTy->isEnumeralType() << ConvTy; - } - return true; - } - } - - return false; -} - Action::OwningStmtResult Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond, DeclPtrTy CondVar) { @@ -531,21 +417,32 @@ Sema::ActOnStartOfSwitchStmt(SourceLocation SwitchLoc, ExprArg Cond, Cond = move(CondE); } - Expr *CondExpr = Cond.takeAs<Expr>(); - if (!CondExpr) + if (!Cond.get()) return StmtError(); - if (getLangOptions().CPlusPlus && - CheckCXXSwitchCondition(*this, SwitchLoc, CondExpr)) - return StmtError(); - + Expr *CondExpr = static_cast<Expr *>(Cond.get()); + OwningExprResult ConvertedCond + = ConvertToIntegralOrEnumerationType(SwitchLoc, move(Cond), + PDiag(diag::err_typecheck_statement_requires_integer), + PDiag(diag::err_switch_incomplete_class_type) + << CondExpr->getSourceRange(), + PDiag(diag::err_switch_explicit_conversion), + PDiag(diag::note_switch_conversion), + PDiag(diag::err_switch_multiple_conversions), + PDiag(diag::note_switch_conversion), + PDiag(0)); + if (ConvertedCond.isInvalid()) + return StmtError(); + + CondExpr = ConvertedCond.takeAs<Expr>(); + if (!CondVar.get()) { CondExpr = MaybeCreateCXXExprWithTemporaries(CondExpr); if (!CondExpr) return StmtError(); } - SwitchStmt *SS = new (Context) SwitchStmt(ConditionVar, CondExpr); + SwitchStmt *SS = new (Context) SwitchStmt(Context, ConditionVar, CondExpr); getSwitchStack().push_back(SS); return Owned(SS); } @@ -584,11 +481,11 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, // be represented by the promoted type. Therefore we need to find // the pre-promotion type of the switch condition. if (!CondExpr->isTypeDependent()) { - if (!CondType->isIntegerType()) { // C99 6.8.4.2p1 - Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer) - << CondType << CondExpr->getSourceRange(); + // We have already converted the expression to an integral or enumeration + // type, when we started the switch statement. If we don't have an + // appropriate type now, just return an error. + if (!CondType->isIntegralOrEnumerationType()) return StmtError(); - } if (CondExpr->isKnownToHaveBooleanValue()) { // switch(bool_expr) {...} is often a programmer error, e.g. @@ -838,6 +735,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, llvm::APSInt Val = (*EDI)->getInitVal(); if(Val.getBitWidth() < CondWidth) Val.extend(CondWidth); + else if (Val.getBitWidth() > CondWidth) + Val.trunc(CondWidth); Val.setIsSigned(CondIsSigned); EnumVals.push_back(std::make_pair(Val, (*EDI))); } @@ -929,8 +828,8 @@ Sema::ActOnWhileStmt(SourceLocation WhileLoc, FullExprArg Cond, DiagnoseUnusedExprResult(bodyStmt); CondResult.release(); - return Owned(new (Context) WhileStmt(ConditionVar, ConditionExpr, bodyStmt, - WhileLoc)); + return Owned(new (Context) WhileStmt(Context, ConditionVar, ConditionExpr, + bodyStmt, WhileLoc)); } Action::OwningStmtResult @@ -999,9 +898,10 @@ Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, first.release(); body.release(); - return Owned(new (Context) ForStmt(First, SecondResult.takeAs<Expr>(), - ConditionVar, Third, Body, - ForLoc, LParenLoc, RParenLoc)); + return Owned(new (Context) ForStmt(Context, First, + SecondResult.takeAs<Expr>(), ConditionVar, + Third, Body, ForLoc, LParenLoc, + RParenLoc)); } Action::OwningStmtResult @@ -1517,14 +1417,14 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, if (InTy->isIntegerType() || InTy->isPointerType()) InputDomain = AD_Int; - else if (InTy->isFloatingType()) + else if (InTy->isRealFloatingType()) InputDomain = AD_FP; else InputDomain = AD_Other; if (OutTy->isIntegerType() || OutTy->isPointerType()) OutputDomain = AD_Int; - else if (OutTy->isFloatingType()) + else if (OutTy->isRealFloatingType()) OutputDomain = AD_FP; else OutputDomain = AD_Other; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp index 307be9d..f121954 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp @@ -27,12 +27,12 @@ using namespace clang; /// \brief Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns NULL. -static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { - if (!D) - return 0; +static NamedDecl *isAcceptableTemplateName(ASTContext &Context, + NamedDecl *Orig) { + NamedDecl *D = Orig->getUnderlyingDecl(); if (isa<TemplateDecl>(D)) - return D; + return Orig; if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { // C++ [temp.local]p1: @@ -68,7 +68,7 @@ static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { LookupResult::Filter filter = R.makeFilter(); while (filter.hasNext()) { NamedDecl *Orig = filter.next(); - NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl()); + NamedDecl *Repl = isAcceptableTemplateName(C, Orig); if (!Repl) filter.erase(); else if (Repl != Orig) { @@ -258,9 +258,9 @@ void Sema::LookupTemplateName(LookupResult &Found, // If we did not find any names, attempt to correct any typos. DeclarationName Name = Found.getLookupName(); if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx, - false, CTC_CXXCasts)) { + false, CTC_CXXCasts)) { FilterAcceptableTemplateNames(Context, Found); - if (!Found.empty() && isa<TemplateDecl>(*Found.begin())) { + if (!Found.empty()) { if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) << Name << LookupCtx << Found.getLookupName() << SS.getRange() @@ -274,10 +274,10 @@ void Sema::LookupTemplateName(LookupResult &Found, if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>()) Diag(Template->getLocation(), diag::note_previous_decl) << Template->getDeclName(); - } else - Found.clear(); + } } else { Found.clear(); + Found.setLookupName(Name); } } @@ -303,7 +303,7 @@ void Sema::LookupTemplateName(LookupResult &Found, // - if the name is found in the context of the entire // postfix-expression and does not name a class template, the name // found in the class of the object expression is used, otherwise - } else { + } else if (!Found.isSuppressingDiagnostics()) { // - if the name found is a class template, it must refer to the same // entity as the one found in the class of the object expression, // otherwise the program is ill-formed. @@ -311,8 +311,9 @@ void Sema::LookupTemplateName(LookupResult &Found, Found.getFoundDecl()->getCanonicalDecl() != FoundOuter.getFoundDecl()->getCanonicalDecl()) { Diag(Found.getNameLoc(), - diag::err_nested_name_member_ref_lookup_ambiguous) - << Found.getLookupName(); + diag::ext_nested_name_member_ref_lookup_ambiguous) + << Found.getLookupName() + << ObjectType; Diag(Found.getRepresentativeDecl()->getLocation(), diag::note_ambig_member_ref_object_type) << ObjectType; @@ -458,7 +459,9 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, SourceLocation KeyLoc, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position) { + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + TypeTy *DefaultArg) { assert(S->isTemplateParamScope() && "Template type parameter not in template parameter scope!"); bool Invalid = false; @@ -489,42 +492,31 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, IdResolver.AddDecl(Param); } - return DeclPtrTy::make(Param); -} - -/// ActOnTypeParameterDefault - Adds a default argument (the type -/// Default) to the given template type parameter (TypeParam). -void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, - SourceLocation EqualLoc, - SourceLocation DefaultLoc, - TypeTy *DefaultT) { - TemplateTypeParmDecl *Parm - = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>()); - - TypeSourceInfo *DefaultTInfo; - GetTypeFromParser(DefaultT, &DefaultTInfo); - - assert(DefaultTInfo && "expected source information for type"); - - // C++0x [temp.param]p9: - // A default template-argument may be specified for any kind of - // template-parameter that is not a template parameter pack. - if (Parm->isParameterPack()) { - Diag(DefaultLoc, diag::err_template_param_pack_default_arg); - return; - } - - // C++ [temp.param]p14: - // A template-parameter shall not be used in its own default argument. - // FIXME: Implement this check! Needs a recursive walk over the types. - - // Check the template argument itself. - if (CheckTemplateArgument(Parm, DefaultTInfo)) { - Parm->setInvalidDecl(); - return; + // Handle the default argument, if provided. + if (DefaultArg) { + TypeSourceInfo *DefaultTInfo; + GetTypeFromParser(DefaultArg, &DefaultTInfo); + + assert(DefaultTInfo && "expected source information for type"); + + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (Ellipsis) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + return DeclPtrTy::make(Param); + } + + // Check the template argument itself. + if (CheckTemplateArgument(Param, DefaultTInfo)) { + Param->setInvalidDecl(); + return DeclPtrTy::make(Param);; + } + + Param->setDefaultArgument(DefaultTInfo, false); } - - Parm->setDefaultArgument(DefaultTInfo, false); + + return DeclPtrTy::make(Param); } /// \brief Check that the type of a non-type template parameter is @@ -548,7 +540,7 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { // (optionally cv-qualified) types: // // -- integral or enumeration type, - if (T->isIntegralType() || T->isEnumeralType() || + if (T->isIntegralOrEnumerationType() || // -- pointer to object or pointer to function, (T->isPointerType() && (T->getAs<PointerType>()->getPointeeType()->isObjectType() || @@ -579,15 +571,13 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { return QualType(); } -/// ActOnNonTypeTemplateParameter - Called when a C++ non-type -/// template parameter (e.g., "int Size" in "template<int Size> -/// class Array") has been parsed. S is the current scope and D is -/// the parsed declarator. Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Depth, - unsigned Position) { - TypeSourceInfo *TInfo = 0; - QualType T = GetTypeForDeclarator(D, S, &TInfo); + unsigned Position, + SourceLocation EqualLoc, + ExprArg DefaultArg) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); assert(S->isTemplateParamScope() && "Non-type template parameter not in template parameter scope!"); @@ -621,34 +611,21 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, S->AddDecl(DeclPtrTy::make(Param)); IdResolver.AddDecl(Param); } - return DeclPtrTy::make(Param); -} - -/// \brief Adds a default argument to the given non-type template -/// parameter. -void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD, - SourceLocation EqualLoc, - ExprArg DefaultE) { - NonTypeTemplateParmDecl *TemplateParm - = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>()); - Expr *Default = static_cast<Expr *>(DefaultE.get()); - - // C++ [temp.param]p14: - // A template-parameter shall not be used in its own default argument. - // FIXME: Implement this check! Needs a recursive walk over the types. - - // Check the well-formedness of the default template argument. - TemplateArgument Converted; - if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default, - Converted)) { - TemplateParm->setInvalidDecl(); - return; + + // Check the well-formedness of the default template argument, if provided. + if (Expr *Default = static_cast<Expr *>(DefaultArg.get())) { + TemplateArgument Converted; + if (CheckTemplateArgument(Param, Param->getType(), Default, Converted)) { + Param->setInvalidDecl(); + return DeclPtrTy::make(Param);; + } + + Param->setDefaultArgument(DefaultArg.takeAs<Expr>(), false); } - - TemplateParm->setDefaultArgument(DefaultE.takeAs<Expr>()); + + return DeclPtrTy::make(Param); } - /// ActOnTemplateTemplateParameter - Called when a C++ template template /// parameter (e.g. T in template <template <typename> class T> class array) /// has been parsed. S is the current scope. @@ -658,7 +635,9 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, IdentifierInfo *Name, SourceLocation NameLoc, unsigned Depth, - unsigned Position) { + unsigned Position, + SourceLocation EqualLoc, + const ParsedTemplateArgument &Default) { assert(S->isTemplateParamScope() && "Template template parameter not in template parameter scope!"); @@ -668,53 +647,33 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, TmpLoc, Depth, Position, Name, (TemplateParameterList*)Params); - // Make sure the parameter is valid. - // FIXME: Decl object is not currently invalidated anywhere so this doesn't - // do anything yet. However, if the template parameter list or (eventual) - // default value is ever invalidated, that will propagate here. - bool Invalid = false; - if (Invalid) { - Param->setInvalidDecl(); - } - - // If the tt-param has a name, then link the identifier into the scope - // and lookup mechanisms. + // If the template template parameter has a name, then link the identifier + // into the scope and lookup mechanisms. if (Name) { S->AddDecl(DeclPtrTy::make(Param)); IdResolver.AddDecl(Param); } - return DeclPtrTy::make(Param); -} - -/// \brief Adds a default argument to the given template template -/// parameter. -void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, - SourceLocation EqualLoc, - const ParsedTemplateArgument &Default) { - TemplateTemplateParmDecl *TemplateParm - = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>()); - - // C++ [temp.param]p14: - // A template-parameter shall not be used in its own default argument. - // FIXME: Implement this check! Needs a recursive walk over the types. - - // Check only that we have a template template argument. We don't want to - // try to check well-formedness now, because our template template parameter - // might have dependent types in its template parameters, which we wouldn't - // be able to match now. - // - // If none of the template template parameter's template arguments mention - // other template parameters, we could actually perform more checking here. - // However, it isn't worth doing. - TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default); - if (DefaultArg.getArgument().getAsTemplate().isNull()) { - Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template) - << DefaultArg.getSourceRange(); - return; + if (!Default.isInvalid()) { + // Check only that we have a template template argument. We don't want to + // try to check well-formedness now, because our template template parameter + // might have dependent types in its template parameters, which we wouldn't + // be able to match now. + // + // If none of the template template parameter's template arguments mention + // other template parameters, we could actually perform more checking here. + // However, it isn't worth doing. + TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default); + if (DefaultArg.getArgument().getAsTemplate().isNull()) { + Diag(DefaultArg.getLocation(), diag::err_template_arg_not_class_template) + << DefaultArg.getSourceRange(); + return DeclPtrTy::make(Param); + } + + Param->setDefaultArgument(DefaultArg, false); } - TemplateParm->setDefaultArgument(DefaultArg); + return DeclPtrTy::make(Param); } /// ActOnTemplateParameterList - Builds a TemplateParameterList that @@ -925,7 +884,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, NewClass->setDescribedClassTemplate(NewTemplate); // Build the type for the class template declaration now. - QualType T = NewTemplate->getInjectedClassNameSpecialization(Context); + QualType T = NewTemplate->getInjectedClassNameSpecialization(); T = Context.getInjectedClassNameType(NewClass, T); assert(T->isDependentType() && "Class template type is not dependent?"); (void)T; @@ -1144,7 +1103,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, NewNonTypeParm->getLocation(), NewNonTypeParm->getDefaultArgument()->getSourceRange())) { NewNonTypeParm->getDefaultArgument()->Destroy(Context); - NewNonTypeParm->setDefaultArgument(0); + NewNonTypeParm->removeDefaultArgument(); } // Merge default arguments for non-type template parameters @@ -1165,7 +1124,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // expression that points to a previous template template // parameter. NewNonTypeParm->setDefaultArgument( - OldNonTypeParm->getDefaultArgument()); + OldNonTypeParm->getDefaultArgument(), + /*Inherited=*/ true); PreviousDefaultArgLoc = OldNonTypeParm->getDefaultArgumentLoc(); } else if (NewNonTypeParm->hasDefaultArgument()) { SawDefaultArgument = true; @@ -1180,7 +1140,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, DiagnoseDefaultTemplateArgument(*this, TPC, NewTemplateParm->getLocation(), NewTemplateParm->getDefaultArgument().getSourceRange())) - NewTemplateParm->setDefaultArgument(TemplateArgumentLoc()); + NewTemplateParm->removeDefaultArgument(); // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm @@ -1199,7 +1159,8 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // FIXME: We need to create a new kind of "default argument" expression // that points to a previous template template parameter. NewTemplateParm->setDefaultArgument( - OldTemplateParm->getDefaultArgument()); + OldTemplateParm->getDefaultArgument(), + /*Inherited=*/ true); PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgument().getLocation(); } else if (NewTemplateParm->hasDefaultArgument()) { @@ -1272,7 +1233,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, TemplateParameterList **ParamLists, unsigned NumParamLists, bool IsFriend, - bool &IsExplicitSpecialization) { + bool &IsExplicitSpecialization, + bool &Invalid) { IsExplicitSpecialization = false; // Find the template-ids that occur within the nested-name-specifier. These @@ -1350,6 +1312,7 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, diag::err_template_spec_needs_template_parameters) << TemplateId << SS.getRange(); + Invalid = true; } else { Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header) << SS.getRange() @@ -1412,7 +1375,13 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, << ExplicitSpecializationsInSpecifier.back(); ExplicitSpecializationsInSpecifier.pop_back(); } - + + // We have a template parameter list with no corresponding scope, which + // means that the resulting template declaration can't be instantiated + // properly (we'll end up with dependent nodes when we shouldn't). + if (!isExplicitSpecHeader) + Invalid = true; + ++Idx; } } @@ -1445,7 +1414,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, "Converted template argument list is too short!"); QualType CanonType; - bool IsCurrentInstantiation = false; if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( @@ -1502,7 +1470,6 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // class name type of the record we just found. assert(ICNT.isCanonical()); CanonType = ICNT; - IsCurrentInstantiation = true; break; } } @@ -1540,8 +1507,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType, - IsCurrentInstantiation); + return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); } Action::TypeResult @@ -1687,12 +1653,18 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, /// example, given "MetaFun::template apply", the scope specifier \p /// SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. -Sema::TemplateTy -Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - TypeTy *ObjectType, - bool EnteringContext) { +TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, + CXXScopeSpec &SS, + UnqualifiedId &Name, + TypeTy *ObjectType, + bool EnteringContext, + TemplateTy &Result) { + if (TemplateKWLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TemplateKWLoc, diag::ext_template_outside_of_template) + << FixItHint::CreateRemoval(TemplateKWLoc); + DeclContext *LookupCtx = 0; if (SS.isSet()) LookupCtx = computeDeclContext(SS, EnteringContext); @@ -1714,26 +1686,25 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // the "template" keyword prior to a template-name that was not a // dependent name. C++ DR468 relaxed this requirement (the // "template" keyword is now permitted). We follow the C++0x - // rules, even in C++03 mode, retroactively applying the DR. - TemplateTy Template; + // rules, even in C++03 mode with a warning, retroactively applying the DR. bool MemberOfUnknownSpecialization; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, - EnteringContext, Template, + EnteringContext, Result, MemberOfUnknownSpecialization); if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && isa<CXXRecordDecl>(LookupCtx) && cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases()) { - // This is a dependent template. + // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diag::err_template_kw_refers_to_non_template) << GetNameFromUnqualifiedId(Name) << Name.getSourceRange() << TemplateKWLoc; - return TemplateTy(); + return TNK_Non_template; } else { // We found something; return it. - return Template; + return TNK; } } @@ -1742,12 +1713,14 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, switch (Name.getKind()) { case UnqualifiedId::IK_Identifier: - return TemplateTy::make(Context.getDependentTemplateName(Qualifier, - Name.Identifier)); + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Name.Identifier)); + return TNK_Dependent_template_name; case UnqualifiedId::IK_OperatorFunctionId: - return TemplateTy::make(Context.getDependentTemplateName(Qualifier, + Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.OperatorFunctionId.Operator)); + return TNK_Dependent_template_name; case UnqualifiedId::IK_LiteralOperatorId: assert(false && "We don't support these; Parse shouldn't have allowed propagation"); @@ -1761,7 +1734,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, << GetNameFromUnqualifiedId(Name) << Name.getSourceRange() << TemplateKWLoc; - return TemplateTy(); + return TNK_Non_template; } bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, @@ -2768,7 +2741,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // conversions (4.7) are applied. QualType ParamType = InstantiatedParamType; QualType ArgType = Arg->getType(); - if (ParamType->isIntegralType() || ParamType->isEnumeralType()) { + if (ParamType->isIntegralOrEnumerationType()) { // C++ [temp.arg.nontype]p1: // A template-argument for a non-type, non-template // template-parameter shall be one of: @@ -2778,7 +2751,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- the name of a non-type template-parameter; or SourceLocation NonConstantLoc; llvm::APSInt Value; - if (!ArgType->isIntegralType() && !ArgType->isEnumeralType()) { + if (!ArgType->isIntegralOrEnumerationType()) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); @@ -3237,9 +3210,32 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, return false; } - if (isa<TemplateTypeParmDecl>(*OldParm)) { - // Okay; all template type parameters are equivalent (since we - // know we're at the same index). + if (TemplateTypeParmDecl *OldTTP + = dyn_cast<TemplateTypeParmDecl>(*OldParm)) { + // Template type parameters are equivalent if either both are template + // type parameter packs or neither are (since we know we're at the same + // index). + TemplateTypeParmDecl *NewTTP = cast<TemplateTypeParmDecl>(*NewParm); + if (OldTTP->isParameterPack() != NewTTP->isParameterPack()) { + // FIXME: Implement the rules in C++0x [temp.arg.template]p5 that + // allow one to match a template parameter pack in the template + // parameter list of a template template parameter to one or more + // template parameters in the template parameter list of the + // corresponding template template argument. + if (Complain) { + unsigned NextDiag = diag::err_template_parameter_pack_non_pack; + if (TemplateArgLoc.isValid()) { + Diag(TemplateArgLoc, + diag::err_template_arg_template_params_mismatch); + NextDiag = diag::note_template_parameter_pack_non_pack; + } + Diag(NewTTP->getLocation(), NextDiag) + << 0 << NewTTP->isParameterPack(); + Diag(OldTTP->getLocation(), diag::note_template_parameter_pack_here) + << 0 << OldTTP->isParameterPack(); + } + return false; + } } else if (NonTypeTemplateParmDecl *OldNTTP = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) { // The types of non-type template parameters must agree. @@ -3634,12 +3630,21 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // template. // FIXME: We probably shouldn't complain about these headers for // friend declarations. + bool Invalid = false; TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, (TemplateParameterList**)TemplateParameterLists.get(), TemplateParameterLists.size(), TUK == TUK_Friend, - isExplicitSpecialization); + isExplicitSpecialization, + Invalid); + if (Invalid) + return true; + + unsigned NumMatchedTemplateParamLists = TemplateParameterLists.size(); + if (TemplateParams) + --NumMatchedTemplateParamLists; + if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; @@ -3660,7 +3665,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Diag(NTTP->getDefaultArgumentLoc(), diag::err_default_arg_in_partial_spec) << DefArg->getSourceRange(); - NTTP->setDefaultArgument(0); + NTTP->removeDefaultArgument(); DefArg->Destroy(Context); } } else { @@ -3669,7 +3674,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Diag(TTP->getDefaultArgument().getLocation(), diag::err_default_arg_in_partial_spec) << TTP->getDefaultArgument().getSourceRange(); - TTP->setDefaultArgument(TemplateArgumentLoc()); + TTP->removeDefaultArgument(); } } } @@ -3831,6 +3836,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial, SequenceNumber); SetNestedNameSpecifier(Partial, SS); + if (NumMatchedTemplateParamLists > 0) { + Partial->setTemplateParameterListsInfo(Context, + NumMatchedTemplateParamLists, + (TemplateParameterList**) TemplateParameterLists.release()); + } if (PrevPartial) { ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); @@ -3888,6 +3898,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Converted, PrevDecl); SetNestedNameSpecifier(Specialization, SS); + if (NumMatchedTemplateParamLists > 0) { + Specialization->setTemplateParameterListsInfo(Context, + NumMatchedTemplateParamLists, + (TemplateParameterList**) TemplateParameterLists.release()); + } if (PrevDecl) { ClassTemplate->getSpecializations().RemoveNode(PrevDecl); @@ -3955,8 +3970,11 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TypeSourceInfo *WrittenTy = Context.getTemplateSpecializationTypeInfo(Name, TemplateNameLoc, TemplateArgs, CanonType); - if (TUK != TUK_Friend) + if (TUK != TUK_Friend) { Specialization->setTypeAsWritten(WrittenTy); + if (TemplateParams) + Specialization->setTemplateKeywordLoc(TemplateParams->getTemplateLoc()); + } TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: @@ -4050,7 +4068,7 @@ static void StripImplicitInstantiation(NamedDecl *D) { /// \param PrevPointOfInstantiation if valid, indicates where the previus /// declaration was instantiated (either implicitly or explicitly). /// -/// \param SuppressNew will be set to true to indicate that the new +/// \param HasNoEffect will be set to true to indicate that the new /// specialization or instantiation has no effect and should be ignored. /// /// \returns true if there was an error that should prevent the introduction of @@ -4061,8 +4079,8 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, NamedDecl *PrevDecl, TemplateSpecializationKind PrevTSK, SourceLocation PrevPointOfInstantiation, - bool &SuppressNew) { - SuppressNew = false; + bool &HasNoEffect) { + HasNoEffect = false; switch (NewTSK) { case TSK_Undeclared: @@ -4119,7 +4137,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, switch (PrevTSK) { case TSK_ExplicitInstantiationDeclaration: // This explicit instantiation declaration is redundant (that's okay). - SuppressNew = true; + HasNoEffect = true; return false; case TSK_Undeclared: @@ -4134,7 +4152,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // of a template appears after a declaration of an explicit // specialization for that template, the explicit instantiation has no // effect. - SuppressNew = true; + HasNoEffect = true; return false; case TSK_ExplicitInstantiationDefinition: @@ -4148,7 +4166,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, diag::note_explicit_instantiation_definition_here); assert(PrevPointOfInstantiation.isValid() && "Explicit instantiation without point of instantiation?"); - SuppressNew = true; + HasNoEffect = true; return false; } break; @@ -4177,7 +4195,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, Diag(PrevDecl->getLocation(), diag::note_previous_template_specialization); } - SuppressNew = true; + HasNoEffect = true; return false; case TSK_ExplicitInstantiationDeclaration: @@ -4194,7 +4212,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, << PrevDecl; Diag(PrevPointOfInstantiation, diag::note_previous_explicit_instantiation); - SuppressNew = true; + HasNoEffect = true; return false; } break; @@ -4343,14 +4361,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, = Specialization->getTemplateSpecializationInfo(); assert(SpecInfo && "Function template specialization info missing?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (!isFriend && CheckSpecializationInstantiationRedecl(FD->getLocation(), TSK_ExplicitSpecialization, Specialization, SpecInfo->getTemplateSpecializationKind(), SpecInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // Mark the prior declaration as an explicit specialization, so that later @@ -4477,13 +4495,13 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // use occurs; no diagnostic is required. assert(MSInfo && "Member specialization info missing?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(Member->getLocation(), TSK_ExplicitSpecialization, Instantiation, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // Check the scope of this explicit specialization. @@ -4544,13 +4562,21 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { } /// \brief Check the scope of an explicit instantiation. -static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, +/// +/// \returns true if a serious error occurs, false otherwise. +static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, SourceLocation InstLoc, bool WasQualifiedName) { DeclContext *ExpectedContext = D->getDeclContext()->getEnclosingNamespaceContext()->getLookupContext(); DeclContext *CurContext = S.CurContext->getLookupContext(); + if (CurContext->isRecord()) { + S.Diag(InstLoc, diag::err_explicit_instantiation_in_class) + << D; + return true; + } + // C++0x [temp.explicit]p2: // An explicit instantiation shall appear in an enclosing namespace of its // template. @@ -4571,7 +4597,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, : diag::warn_explicit_instantiation_out_of_scope_0x) << D; S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); - return; + return false; } // C++0x [temp.explicit]p2: @@ -4580,10 +4606,10 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, // its template is declared or, if that namespace is inline (7.3.1), any // namespace from its enclosing namespace set. if (WasQualifiedName) - return; + return false; if (CurContext->Equals(ExpectedContext)) - return; + return false; S.Diag(InstLoc, S.getLangOptions().CPlusPlus0x? @@ -4591,6 +4617,7 @@ static void CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, : diag::warn_explicit_instantiation_unqualified_wrong_namespace_0x) << D << ExpectedContext; S.Diag(D->getLocation(), diag::note_explicit_instantiation_here); + return false; } /// \brief Determine whether the given scope specifier has a template-id in it. @@ -4685,42 +4712,46 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + TemplateSpecializationKind PrevDecl_TSK + = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; + // C++0x [temp.explicit]p2: // [...] An explicit instantiation shall appear in an enclosing // namespace of its template. [...] // // This is C++ DR 275. - CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, - SS.isSet()); + if (CheckExplicitInstantiationScope(*this, ClassTemplate, TemplateNameLoc, + SS.isSet())) + return true; ClassTemplateSpecializationDecl *Specialization = 0; bool ReusedDecl = false; + bool HasNoEffect = false; if (PrevDecl) { - bool SuppressNew = false; if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, - PrevDecl, - PrevDecl->getSpecializationKind(), + PrevDecl, PrevDecl_TSK, PrevDecl->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return DeclPtrTy::make(PrevDecl); - if (SuppressNew) - return DeclPtrTy::make(PrevDecl); - - if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation || - PrevDecl->getSpecializationKind() == TSK_Undeclared) { + // Even though HasNoEffect == true means that this explicit instantiation + // has no effect on semantics, we go on to put its syntax in the AST. + + if (PrevDecl_TSK == TSK_ImplicitInstantiation || + PrevDecl_TSK == TSK_Undeclared) { // Since the only prior class template specialization with these // arguments was referenced but not declared, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. + // declaration node as our own, updating the source location + // for the template name to reflect our new declaration. + // (Other source locations will be updated later.) Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; ReusedDecl = true; } } - + if (!Specialization) { // Create a new class template specialization declaration node for // this explicit specialization. @@ -4732,15 +4763,16 @@ Sema::ActOnExplicitInstantiation(Scope *S, Converted, PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (PrevDecl) { - // Remove the previous declaration from the folding set, since we want - // to introduce a new declaration. - ClassTemplate->getSpecializations().RemoveNode(PrevDecl); - ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); - } - - // Insert the new specialization. - ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); + if (!HasNoEffect) { + if (PrevDecl) { + // Remove the previous declaration from the folding set, since we want + // to introduce a new declaration. + ClassTemplate->getSpecializations().RemoveNode(PrevDecl); + ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + } + // Insert the new specialization. + ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); + } } // Build the fully-sugared type for this explicit instantiation as @@ -4757,12 +4789,21 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); - if (!ReusedDecl) { - // Add the explicit instantiation into its lexical context. However, - // since explicit instantiations are never found by name lookup, we - // just put it into the declaration context directly. - Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Specialization); + // Set source locations for keywords. + Specialization->setExternLoc(ExternLoc); + Specialization->setTemplateKeywordLoc(TemplateLoc); + + // Add the explicit instantiation into its lexical context. However, + // since explicit instantiations are never found by name lookup, we + // just put it into the declaration context directly. + Specialization->setLexicalDeclContext(CurContext); + CurContext->addDecl(Specialization); + + // Syntax is now OK, so return if it has no other effect on semantics. + if (HasNoEffect) { + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); + return DeclPtrTy::make(Specialization); } // C++ [temp.explicit]p3: @@ -4777,8 +4818,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->getDefinition()); if (!Def) InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); - else if (TSK == TSK_ExplicitInstantiationDefinition) + else if (TSK == TSK_ExplicitInstantiationDefinition) { MarkVTableUsed(TemplateNameLoc, Specialization, true); + Specialization->setPointOfInstantiation(Def->getPointOfInstantiation()); + } // Instantiate the members of this class template specialization. Def = cast_or_null<ClassTemplateSpecializationDecl>( @@ -4795,6 +4838,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); } + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); return DeclPtrTy::make(Specialization); } @@ -4847,7 +4892,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, // // C++98 has the same restriction, just worded differently. if (!ScopeSpecifierHasTemplateId(SS)) - Diag(TemplateLoc, diag::err_explicit_instantiation_without_qualified_id) + Diag(TemplateLoc, diag::ext_explicit_instantiation_without_qualified_id) << Record << SS.getRange(); // C++0x [temp.explicit]p2: @@ -4872,15 +4917,15 @@ Sema::ActOnExplicitInstantiation(Scope *S, PrevDecl = Record; if (PrevDecl) { MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); - bool SuppressNew = false; + bool HasNoEffect = false; assert(MSInfo && "No member specialization information?"); if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK, PrevDecl, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; - if (SuppressNew) + if (HasNoEffect) return TagD; } @@ -4947,7 +4992,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, S = S->getParent(); // Determine the type of the declaration. - QualType R = GetTypeForDeclarator(D, S, 0); + TypeSourceInfo *T = GetTypeForDeclarator(D, S); + QualType R = T->getType(); if (R.isNull()) return true; @@ -5019,7 +5065,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // C++98 has the same restriction, just worded differently. if (!ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) Diag(D.getIdentifierLoc(), - diag::err_explicit_instantiation_without_qualified_id) + diag::ext_explicit_instantiation_without_qualified_id) << Prev << D.getCXXScopeSpec().getRange(); // Check the scope of this explicit instantiation. @@ -5028,13 +5074,13 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // Verify that it is okay to explicitly instantiate here. MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); assert(MSInfo && "Missing static data member specialization info?"); - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev, MSInfo->getTemplateSpecializationKind(), MSInfo->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; - if (SuppressNew) + if (HasNoEffect) return DeclPtrTy(); // Instantiate static data member. @@ -5131,17 +5177,17 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, PrevDecl = Specialization; if (PrevDecl) { - bool SuppressNew = false; + bool HasNoEffect = false; if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, PrevDecl, PrevDecl->getTemplateSpecializationKind(), PrevDecl->getPointOfInstantiation(), - SuppressNew)) + HasNoEffect)) return true; // FIXME: We may still want to build some representation of this // explicit specialization. - if (SuppressNew) + if (HasNoEffect) return DeclPtrTy(); } @@ -5163,7 +5209,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, D.getCXXScopeSpec().isSet() && !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) Diag(D.getIdentifierLoc(), - diag::err_explicit_instantiation_without_qualified_id) + diag::ext_explicit_instantiation_without_qualified_id) << Specialization << D.getCXXScopeSpec().getRange(); CheckExplicitInstantiationScope(*this, @@ -5200,31 +5246,20 @@ Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return Context.getDependentNameType(Kwd, NNS, Name).getAsOpaquePtr(); } -static void FillTypeLoc(DependentNameTypeLoc TL, - SourceLocation TypenameLoc, - SourceRange QualifierRange, - SourceLocation NameLoc) { - TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(QualifierRange); - TL.setNameLoc(NameLoc); -} - -static void FillTypeLoc(ElaboratedTypeLoc TL, - SourceLocation TypenameLoc, - SourceRange QualifierRange) { - // FIXME: inner locations. - TL.setKeywordLoc(TypenameLoc); - TL.setQualifierRange(QualifierRange); -} - Sema::TypeResult -Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - const IdentifierInfo &II, SourceLocation IdLoc) { +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, + SourceLocation IdLoc) { NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); if (!NNS) return true; + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TypenameLoc, diag::ext_typename_outside_of_template) + << FixItHint::CreateRemoval(TypenameLoc); + QualType T = CheckTypenameType(ETK_Typename, NNS, II, TypenameLoc, SS.getRange(), IdLoc); if (T.isNull()) @@ -5233,44 +5268,82 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); if (isa<DependentNameType>(T)) { DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - // FIXME: fill inner type loc - FillTypeLoc(TL, TypenameLoc, SS.getRange(), IdLoc); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierRange(SS.getRange()); + TL.setNameLoc(IdLoc); } else { ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); - // FIXME: fill inner type loc - FillTypeLoc(TL, TypenameLoc, SS.getRange()); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierRange(SS.getRange()); + cast<TypeSpecTypeLoc>(TL.getNamedTypeLoc()).setNameLoc(IdLoc); } return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } Sema::TypeResult -Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - SourceLocation TemplateLoc, TypeTy *Ty) { - QualType T = GetTypeFromParser(Ty); +Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, SourceLocation TemplateLoc, + TypeTy *Ty) { + if (TypenameLoc.isValid() && S && !S->getTemplateParamParent() && + !getLangOptions().CPlusPlus0x) + Diag(TypenameLoc, diag::ext_typename_outside_of_template) + << FixItHint::CreateRemoval(TypenameLoc); + + TypeSourceInfo *InnerTSI = 0; + QualType T = GetTypeFromParser(Ty, &InnerTSI); NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - const TemplateSpecializationType *TemplateId - = T->getAs<TemplateSpecializationType>(); - assert(TemplateId && "Expected a template specialization type"); + + assert(isa<TemplateSpecializationType>(T) && + "Expected a template specialization type"); if (computeDeclContext(SS, false)) { // If we can compute a declaration context, then the "typename" // keyword was superfluous. Just build an ElaboratedType to keep // track of the nested-name-specifier. + + // Push the inner type, preserving its source locations if possible. + TypeLocBuilder Builder; + if (InnerTSI) + Builder.pushFullCopy(InnerTSI->getTypeLoc()); + else + Builder.push<TemplateSpecializationTypeLoc>(T).initialize(TemplateLoc); + T = Context.getElaboratedType(ETK_Typename, NNS, T); - TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - ElaboratedTypeLoc TL = cast<ElaboratedTypeLoc>(TSI->getTypeLoc()); - // FIXME: fill inner type loc - FillTypeLoc(TL, TypenameLoc, SS.getRange()); + ElaboratedTypeLoc TL = Builder.push<ElaboratedTypeLoc>(T); + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierRange(SS.getRange()); + + TypeSourceInfo *TSI = Builder.getTypeSourceInfo(Context, T); return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } - T = Context.getDependentNameType(ETK_Typename, NNS, TemplateId); + // TODO: it's really silly that we make a template specialization + // type earlier only to drop it again here. + TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); + DependentTemplateName *DTN = + TST->getTemplateName().getAsDependentTemplateName(); + assert(DTN && "dependent template has non-dependent name?"); + T = Context.getDependentTemplateSpecializationType(ETK_Typename, NNS, + DTN->getIdentifier(), + TST->getNumArgs(), + TST->getArgs()); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); - DependentNameTypeLoc TL = cast<DependentNameTypeLoc>(TSI->getTypeLoc()); - // FIXME: fill inner type loc - FillTypeLoc(TL, TypenameLoc, SS.getRange(), TemplateLoc); + DependentTemplateSpecializationTypeLoc TL = + cast<DependentTemplateSpecializationTypeLoc>(TSI->getTypeLoc()); + if (InnerTSI) { + TemplateSpecializationTypeLoc TSTL = + cast<TemplateSpecializationTypeLoc>(InnerTSI->getTypeLoc()); + TL.setLAngleLoc(TSTL.getLAngleLoc()); + TL.setRAngleLoc(TSTL.getRAngleLoc()); + for (unsigned I = 0, E = TST->getNumArgs(); I != E; ++I) + TL.setArgLocInfo(I, TSTL.getArgLocInfo(I)); + } else { + TL.initializeLocal(SourceLocation()); + } + TL.setKeywordLoc(TypenameLoc); + TL.setQualifierRange(SS.getRange()); return CreateLocInfoType(T, TSI).getAsOpaquePtr(); } @@ -5297,7 +5370,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // the "typename" keyword itself is superfluous. In C++03, the // program is actually ill-formed. However, DR 382 (in C++0x CD1) // allows such extraneous "typename" keywords, and we retroactively - // apply this DR to C++03 code. In any case we continue. + // apply this DR to C++03 code with only a warning. In any case we continue. if (RequireCompleteDeclContext(SS, Ctx)) return QualType(); @@ -5317,7 +5390,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, return Context.getDependentNameType(Keyword, NNS, &II); case LookupResult::Found: - if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { + if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { // We found a type. Build an ElaboratedType, since the // typename-specifier was just sugar. return Context.getElaboratedType(ETK_Typename, NNS, @@ -5399,87 +5472,9 @@ namespace { Sema::OwningExprResult TransformExpr(Expr *E) { return getSema().Owned(E->Retain()); } - - /// \brief Transforms a typename type by determining whether the type now - /// refers to a member of the current instantiation, and then - /// type-checking and building an ElaboratedType (when possible). - QualType TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType); }; } -QualType -CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB, - DependentNameTypeLoc TL, - QualType ObjectType) { - DependentNameType *T = TL.getTypePtr(); - - NestedNameSpecifier *NNS - = TransformNestedNameSpecifier(T->getQualifier(), - TL.getQualifierRange(), - ObjectType); - if (!NNS) - return QualType(); - - // If the nested-name-specifier did not change, and we cannot compute the - // context corresponding to the nested-name-specifier, then this - // typename type will not change; exit early. - CXXScopeSpec SS; - SS.setRange(TL.getQualifierRange()); - SS.setScopeRep(NNS); - - QualType Result; - if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0) - Result = QualType(T, 0); - - // Rebuild the typename type, which will probably turn into a - // ElaboratedType. - else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - Result = QualType(T, 0); - else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), - NNS, NewTemplateId); - } else - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - - if (Result.isNull()) - return QualType(); - - if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { - QualType NamedT = ElabT->getNamedType(); - if (isa<TemplateSpecializationType>(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } - ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { - DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); - NewTL.setKeywordLoc(TL.getKeywordLoc()); - NewTL.setQualifierRange(TL.getQualifierRange()); - NewTL.setNameLoc(TL.getNameLoc()); - } - return Result; -} - /// \brief Rebuilds a type within the context of the current instantiation. /// /// The type \p T is part of the type of an out-of-line member definition of diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.h b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.h index ca59e27..b3f4651 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.h +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.h @@ -36,10 +36,14 @@ namespace clang { /// When instantiating X<int>::Y<17>::f, the multi-level template argument /// list will contain a template argument list (int) at depth 0 and a /// template argument list (17) at depth 1. - struct MultiLevelTemplateArgumentList { + class MultiLevelTemplateArgumentList { + public: + typedef std::pair<const TemplateArgument *, unsigned> ArgList; + + private: /// \brief The template argument lists, stored from the innermost template /// argument list (first) to the outermost template argument list (last). - llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists; + llvm::SmallVector<ArgList, 4> TemplateArgumentLists; public: /// \brief Construct an empty set of template argument lists. @@ -48,7 +52,7 @@ namespace clang { /// \brief Construct a single-level template argument list. explicit MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { - TemplateArgumentLists.push_back(&TemplateArgs); + addOuterTemplateArguments(&TemplateArgs); } /// \brief Determine the number of levels in this template argument @@ -58,8 +62,8 @@ namespace clang { /// \brief Retrieve the template argument at a given depth and index. const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { assert(Depth < TemplateArgumentLists.size()); - assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size()); - return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index); + assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second); + return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index]; } /// \brief Determine whether there is a non-NULL template argument at the @@ -69,7 +73,7 @@ namespace clang { bool hasTemplateArgument(unsigned Depth, unsigned Index) const { assert(Depth < TemplateArgumentLists.size()); - if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size()) + if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second) return false; return !(*this)(Depth, Index).isNull(); @@ -78,12 +82,21 @@ namespace clang { /// \brief Add a new outermost level to the multi-level template argument /// list. void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { - TemplateArgumentLists.push_back(TemplateArgs); + TemplateArgumentLists.push_back( + ArgList(TemplateArgs->getFlatArgumentList(), + TemplateArgs->flat_size())); + } + + /// \brief Add a new outmost level to the multi-level template argument + /// list. + void addOuterTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs) { + TemplateArgumentLists.push_back(ArgList(Args, NumArgs)); } /// \brief Retrieve the innermost template argument list. - const TemplateArgumentList &getInnermost() const { - return *TemplateArgumentLists.front(); + const ArgList &getInnermost() const { + return TemplateArgumentLists.front(); } }; diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp index 88ceeca..403d554 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2624,6 +2624,18 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, OnlyDeduced, Depth, Used); break; + case Type::DependentTemplateSpecialization: { + const DependentTemplateSpecializationType *Spec + = cast<DependentTemplateSpecializationType>(T); + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, Spec->getQualifier(), + OnlyDeduced, Depth, Used); + for (unsigned I = 0, N = Spec->getNumArgs(); I != N; ++I) + MarkUsedTemplateParameters(SemaRef, Spec->getArg(I), OnlyDeduced, Depth, + Used); + break; + } + case Type::TypeOf: if (!OnlyDeduced) MarkUsedTemplateParameters(SemaRef, diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp index 1adf594..0cdc8a1 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -63,7 +63,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { // We're done when we hit an explicit specialization. - if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization) + if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa<ClassTemplatePartialSpecializationDecl>(Spec)) break; Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); @@ -104,6 +105,15 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, RelativeToPrimary = false; continue; } + } else if (CXXRecordDecl *Rec = dyn_cast<CXXRecordDecl>(Ctx)) { + if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { + QualType T = ClassTemplate->getInjectedClassNameSpecialization(); + const TemplateSpecializationType *TST + = cast<TemplateSpecializationType>(Context.getCanonicalType(T)); + Result.addOuterTemplateArguments(TST->getArgs(), TST->getNumArgs()); + if (ClassTemplate->isMemberSpecialization()) + break; + } } Ctx = Ctx->getParent(); @@ -620,6 +630,14 @@ namespace { QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL, QualType ObjectType); + + Sema::OwningExprResult TransformCallExpr(CallExpr *CE) { + getSema().CallsUndergoingInstantiation.push_back(CE); + OwningExprResult Result = + TreeTransform<TemplateInstantiator>::TransformCallExpr(CE); + getSema().CallsUndergoingInstantiation.pop_back(); + return move(Result); + } }; } @@ -1049,6 +1067,9 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); CurrentInstantiationScope->InstantiatedLocal(OldParm, NewParm); + // Set DeclContext if inside a Block. + NewParm->setDeclContext(CurContext); + return NewParm; } @@ -1216,7 +1237,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation), Fields.data(), Fields.size(), SourceLocation(), SourceLocation(), 0); - CheckCompletedCXXClass(/*Scope=*/0, Instantiation); + CheckCompletedCXXClass(Instantiation); if (Instantiation->isInvalidDecl()) Invalid = true; @@ -1434,7 +1455,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, SuppressNew) continue; - if (Function->getBody()) + if (Function->hasBody()) continue; if (TSK == TSK_ExplicitInstantiationDefinition) { @@ -1444,7 +1465,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, // specialization and is only an explicit instantiation definition // of members whose definition is visible at the point of // instantiation. - if (!Pattern->getBody()) + if (!Pattern->hasBody()) continue; Function->setTemplateSpecializationKind(TSK, PointOfInstantiation); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 834b86d..2fd3528 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -42,12 +42,13 @@ namespace { // FIXME: Once we get closer to completion, replace these manually-written // declarations with automatically-generated ones from - // clang/AST/DeclNodes.def. + // clang/AST/DeclNodes.inc. Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitVarDecl(VarDecl *D); + Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitFieldDecl(FieldDecl *D); Decl *VisitStaticAssertDecl(StaticAssertDecl *D); Decl *VisitEnumDecl(EnumDecl *D); @@ -142,14 +143,29 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl, return false; } -// FIXME: Is this too simple? +// FIXME: Is this still too simple? void TemplateDeclInstantiator::InstantiateAttrs(Decl *Tmpl, Decl *New) { - for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; + for (const Attr *TmplAttr = Tmpl->getAttrs(); TmplAttr; TmplAttr = TmplAttr->getNext()) { - + // FIXME: This should be generalized to more than just the AlignedAttr. + if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) { + if (Aligned->isDependent()) { + // The alignment expression is not potentially evaluated. + EnterExpressionEvaluationContext Unevaluated(SemaRef, + Action::Unevaluated); + + OwningExprResult Result = SemaRef.SubstExpr(Aligned->getAlignmentExpr(), + TemplateArgs); + if (!Result.isInvalid()) + // FIXME: Is this the correct source location? + SemaRef.AddAlignedAttr(Aligned->getAlignmentExpr()->getExprLoc(), + New, Result.takeAs<Expr>()); + continue; + } + } + // FIXME: Is cloning correct for all attributes? Attr *NewAttr = TmplAttr->clone(SemaRef.Context); - New->addAttr(NewAttr); } } @@ -360,7 +376,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { Var->setLexicalDeclContext(D->getLexicalDeclContext()); Var->setAccess(D->getAccess()); - Var->setUsed(D->isUsed()); + + if (!D->isStaticDataMember()) + Var->setUsed(D->isUsed(false)); // FIXME: In theory, we could have a previous declaration for variables that // are not static data members. @@ -373,15 +391,16 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration); if (D->isOutOfLine()) { - D->getLexicalDeclContext()->addDecl(Var); + if (!D->isStaticDataMember()) + D->getLexicalDeclContext()->addDecl(Var); Owner->makeDeclVisibleInContext(Var); } else { Owner->addDecl(Var); - if (Owner->isFunctionOrMethod()) SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var); } - + InstantiateAttrs(D, Var); + // Link instantiations of static data members back to the template from // which they were instantiated. if (Var->isStaticDataMember()) @@ -436,6 +455,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { return Var; } +Decl *TemplateDeclInstantiator::VisitAccessSpecDecl(AccessSpecDecl *D) { + AccessSpecDecl* AD + = AccessSpecDecl::Create(SemaRef.Context, D->getAccess(), Owner, + D->getAccessSpecifierLoc(), D->getColonLoc()); + Owner->addHiddenDecl(AD); + return AD; +} + Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); @@ -793,7 +820,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // Trigger creation of the type for the instantiation. SemaRef.Context.getInjectedClassNameType(RecordInst, - Inst->getInjectedClassNameSpecialization(SemaRef.Context)); + Inst->getInjectedClassNameSpecialization()); // Finish handling of friends. if (isFriend) { @@ -951,9 +978,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, void *InsertPos = 0; if (FunctionTemplate && !TemplateParams) { llvm::FoldingSetNodeID ID; - FunctionTemplateSpecializationInfo::Profile(ID, - TemplateArgs.getInnermost().getFlatArgumentList(), - TemplateArgs.getInnermost().flat_size(), + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first, + Innermost.second, SemaRef.Context); FunctionTemplateSpecializationInfo *Info @@ -1062,8 +1090,12 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } } else if (FunctionTemplate) { // Record this function template specialization. + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); Function->setFunctionTemplateSpecialization(FunctionTemplate, - &TemplateArgs.getInnermost(), + new (SemaRef.Context) TemplateArgumentList(SemaRef.Context, + Innermost.first, + Innermost.second), InsertPos); } else if (isFriend && D->isThisDeclarationADefinition()) { // TODO: should we remember this connection regardless of whether @@ -1154,7 +1186,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->isThisDeclarationADefinition()) { // Check for a function body. const FunctionDecl *Definition = 0; - if (Function->getBody(Definition) && + if (Function->hasBody(Definition) && Definition->getTemplateSpecializationKind() == TSK_Undeclared) { SemaRef.Diag(Function->getLocation(), diag::err_redefinition) << Function->getDeclName(); @@ -1170,7 +1202,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, ((*R)->getFriendObjectKind() != Decl::FOK_None)) { if (const FunctionDecl *RPattern = (*R)->getTemplateInstantiationPattern()) - if (RPattern->getBody(RPattern)) { + if (RPattern->hasBody(RPattern)) { SemaRef.Diag(Function->getLocation(), diag::err_redefinition) << Function->getDeclName(); SemaRef.Diag((*R)->getLocation(), diag::note_previous_definition); @@ -1200,9 +1232,10 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // template. Check whether there is already a function template // specialization for this particular set of template arguments. llvm::FoldingSetNodeID ID; - FunctionTemplateSpecializationInfo::Profile(ID, - TemplateArgs.getInnermost().getFlatArgumentList(), - TemplateArgs.getInnermost().flat_size(), + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); + FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first, + Innermost.second, SemaRef.Context); FunctionTemplateSpecializationInfo *Info @@ -1347,8 +1380,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Method->setDescribedFunctionTemplate(FunctionTemplate); } else if (FunctionTemplate) { // Record this function template specialization. + std::pair<const TemplateArgument *, unsigned> Innermost + = TemplateArgs.getInnermost(); Method->setFunctionTemplateSpecialization(FunctionTemplate, - &TemplateArgs.getInnermost(), + new (SemaRef.Context) TemplateArgumentList(SemaRef.Context, + Innermost.first, + Innermost.second), InsertPos); } else if (!isFriend) { // Record that this is an instantiation of a member function. @@ -1485,7 +1522,7 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( if (Invalid) Param->setInvalidDecl(); - Param->setDefaultArgument(D->getDefaultArgument()); + Param->setDefaultArgument(D->getDefaultArgument(), false); // Introduce this template parameter's instantiation into the instantiation // scope. @@ -1513,7 +1550,7 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDepth() - 1, D->getPosition(), D->getIdentifier(), InstParams); - Param->setDefaultArgument(D->getDefaultArgument()); + Param->setDefaultArgument(D->getDefaultArgument(), false); // Introduce this template parameter's instantiation into the instantiation // scope. @@ -1966,6 +2003,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, Proto->getExtInfo())); } + InstantiateAttrs(Tmpl, New); + return false; } @@ -2011,7 +2050,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive, bool DefinitionRequired) { - if (Function->isInvalidDecl() || Function->getBody()) + if (Function->isInvalidDecl() || Function->hasBody()) return; // Never instantiate an explicit specialization. @@ -2568,7 +2607,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); if (ClassTemplate) { - T = ClassTemplate->getInjectedClassNameSpecialization(Context); + T = ClassTemplate->getInjectedClassNameSpecialization(); } else if (ClassTemplatePartialSpecializationDecl *PartialSpec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { ClassTemplate = PartialSpec->getSpecializedTemplate(); diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp index 35efa61..a4fc98c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaType.cpp @@ -383,8 +383,12 @@ static QualType ConvertDeclSpecToType(Sema &TheSema, } else if (DS.isTypeAltiVecVector()) { unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result)); assert(typeSize > 0 && "type size for vector must be greater than 0 bits"); - Result = Context.getVectorType(Result, 128/typeSize, true, - DS.isTypeAltiVecPixel()); + VectorType::AltiVecSpecific AltiVecSpec = VectorType::AltiVec; + if (DS.isTypeAltiVecPixel()) + AltiVecSpec = VectorType::Pixel; + else if (DS.isTypeAltiVecBool()) + AltiVecSpec = VectorType::Bool; + Result = Context.getVectorType(Result, 128/typeSize, AltiVecSpec); } assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary && @@ -472,12 +476,49 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { return "type name"; } +QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, + Qualifiers Qs) { + // Enforce C99 6.7.3p2: "Types other than pointer types derived from + // object or incomplete types shall not be restrict-qualified." + if (Qs.hasRestrict()) { + unsigned DiagID = 0; + QualType ProblemTy; + + const Type *Ty = T->getCanonicalTypeInternal().getTypePtr(); + if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) { + if (!RTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<ReferenceType>()->getPointeeType(); + } + } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<PointerType>()->getPointeeType(); + } + } else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) { + if (!PTy->getPointeeType()->isIncompleteOrObjectType()) { + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T->getAs<PointerType>()->getPointeeType(); + } + } else if (!Ty->isDependentType()) { + // FIXME: this deserves a proper diagnostic + DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; + ProblemTy = T; + } + + if (DiagID) { + Diag(Loc, DiagID) << ProblemTy; + Qs.removeRestrict(); + } + } + + return Context.getQualifiedType(T, Qs); +} + /// \brief Build a pointer type. /// /// \param T The type to which we'll be building a pointer. /// -/// \param Quals The cvr-qualifiers to be applied to the pointer type. -/// /// \param Loc The location of the entity whose type involves this /// pointer type or, if there is no such entity, the location of the /// type that will have pointer type. @@ -487,7 +528,7 @@ static std::string getPrintableNameForEntity(DeclarationName Entity) { /// /// \returns A suitable pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildPointerType(QualType T, unsigned Quals, +QualType Sema::BuildPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (T->isReferenceType()) { // C++ 8.3.2p4: There shall be no ... pointers to references ... @@ -496,28 +537,16 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, return QualType(); } - Qualifiers Qs = Qualifiers::fromCVRMask(Quals); - - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Qs.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - Qs.removeRestrict(); - } - assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType"); // Build the pointer type. - return Context.getQualifiedType(Context.getPointerType(T), Qs); + return Context.getPointerType(T); } /// \brief Build a reference type. /// /// \param T The type to which we'll be building a reference. /// -/// \param CVR The cvr-qualifiers to be applied to the reference type. -/// /// \param Loc The location of the entity whose type involves this /// reference type or, if there is no such entity, the location of the /// type that will have reference type. @@ -528,10 +557,8 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals, /// \returns A suitable reference type, if there are no /// errors. Otherwise, returns a NULL type. QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, - unsigned CVR, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity) { - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>(); // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a @@ -562,31 +589,10 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, return QualType(); } - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - Quals.removeRestrict(); - } - - // 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. - // - // We diagnose extraneous cv-qualifiers for the non-typedef, - // non-template type argument case within the parser. Here, we just - // ignore any extraneous cv-qualifiers. - Quals.removeConst(); - Quals.removeVolatile(); - // Handle restrict on references. if (LValueRef) - return Context.getQualifiedType( - Context.getLValueReferenceType(T, SpelledAsLValue), Quals); - return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals); + return Context.getLValueReferenceType(T, SpelledAsLValue); + return Context.getRValueReferenceType(T); } /// \brief Build an array type. @@ -597,9 +603,6 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, /// /// \param ArraySize Expression describing the size of the array. /// -/// \param Quals The cvr-qualifiers to be applied to the array's -/// element type. -/// /// \param Loc The location of the entity whose type involves this /// array type or, if there is no such entity, the location of the /// type that will have array type. @@ -815,7 +818,7 @@ QualType Sema::BuildFunctionType(QualType T, << T->isFunctionType() << T; return QualType(); } - + bool Invalid = false; for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) { QualType ParamType = adjustParameterType(ParamTypes[Idx]); @@ -846,10 +849,8 @@ QualType Sema::BuildFunctionType(QualType T, /// \returns a member pointer type, if successful, or a NULL type if there was /// an error. QualType Sema::BuildMemberPointerType(QualType T, QualType Class, - unsigned CVR, SourceLocation Loc, + SourceLocation Loc, DeclarationName Entity) { - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - // Verify that we're not building a pointer to pointer to function with // exception specification. if (CheckDistantExceptionSpec(T)) { @@ -863,7 +864,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, T = Context.getCanonicalType(T); } - // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member + // C++ 8.3.3p3: A pointer to member shall not point to ... a member // with reference type, or "cv void." if (T->isReferenceType()) { Diag(Loc, diag::err_illegal_decl_mempointer_to_reference) @@ -877,24 +878,12 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return QualType(); } - // Enforce C99 6.7.3p2: "Types other than pointer types derived from - // object or incomplete types shall not be restrict-qualified." - if (Quals.hasRestrict() && !T->isIncompleteOrObjectType()) { - Diag(Loc, diag::err_typecheck_invalid_restrict_invalid_pointee) - << T; - - // FIXME: If we're doing this as part of template instantiation, - // we should return immediately. - Quals.removeRestrict(); - } - if (!Class->isDependentType() && !Class->isRecordType()) { Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class; return QualType(); } - return Context.getQualifiedType( - Context.getMemberPointerType(T, Class.getTypePtr()), Quals); + return Context.getMemberPointerType(T, Class.getTypePtr()); } /// \brief Build a block pointer type. @@ -912,7 +901,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, /// /// \returns A suitable block pointer type, if there are no /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, +QualType Sema::BuildBlockPointerType(QualType T, SourceLocation Loc, DeclarationName Entity) { if (!T->isFunctionType()) { @@ -920,8 +909,7 @@ QualType Sema::BuildBlockPointerType(QualType T, unsigned CVR, return QualType(); } - Qualifiers Quals = Qualifiers::fromCVRMask(CVR); - return Context.getQualifiedType(Context.getBlockPointerType(T), Quals); + return Context.getBlockPointerType(T); } QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) { @@ -947,9 +935,11 @@ QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) { /// If OwnedDecl is non-NULL, and this declarator's decl-specifier-seq /// owns the declaration of a type (e.g., the definition of a struct /// type), then *OwnedDecl will receive the owned declaration. -QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, - TypeSourceInfo **TInfo, - TagDecl **OwnedDecl) { +/// +/// The result of this call will never be null, but the associated +/// type may be a null type if there's an unrecoverable error. +TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, + TagDecl **OwnedDecl) { // Determine the type of the declarator. Not all forms of declarator // have a type. QualType T; @@ -980,22 +970,18 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Constructors and destructors don't have return types. Use // "void" instead. T = Context.VoidTy; - - if (TInfo) - ReturnTypeInfo = Context.getTrivialTypeSourceInfo(T, - D.getName().StartLocation); break; case UnqualifiedId::IK_ConversionFunctionId: // The result type of a conversion function is the type that it // converts to. T = GetTypeFromParser(D.getName().ConversionFunctionId, - TInfo? &ReturnTypeInfo : 0); + &ReturnTypeInfo); break; } if (T.isNull()) - return T; + return Context.getNullTypeSourceInfo(); if (T == Context.UndeducedAutoTy) { int Error = -1; @@ -1059,8 +1045,9 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (!LangOpts.Blocks) Diag(DeclType.Loc, diag::err_blocks_disable); - T = BuildBlockPointerType(T, DeclType.Cls.TypeQuals, D.getIdentifierLoc(), - Name); + T = BuildBlockPointerType(T, D.getIdentifierLoc(), Name); + if (DeclType.Cls.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals); break; case DeclaratorChunk::Pointer: // Verify that we're not building a pointer to pointer to function with @@ -1072,15 +1059,15 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } if (getLangOptions().ObjC1 && T->getAs<ObjCObjectType>()) { T = Context.getObjCObjectPointerType(T); - T = Context.getCVRQualifiedType(T, DeclType.Ptr.TypeQuals); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); break; } - T = BuildPointerType(T, DeclType.Ptr.TypeQuals, DeclType.Loc, Name); + T = BuildPointerType(T, DeclType.Loc, Name); + if (DeclType.Ptr.TypeQuals) + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals); break; case DeclaratorChunk::Reference: { - Qualifiers Quals; - if (DeclType.Ref.HasRestrict) Quals.addRestrict(); - // Verify that we're not building a reference to pointer to function with // exception specification. if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -1088,8 +1075,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); // Build the type anyway. } - T = BuildReferenceType(T, DeclType.Ref.LValueRef, Quals, - DeclType.Loc, Name); + T = BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name); + + Qualifiers Quals; + if (DeclType.Ref.HasRestrict) + T = BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict); break; } case DeclaratorChunk::Array: { @@ -1139,6 +1129,48 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.setInvalidType(true); } + // cv-qualifiers on return types are pointless except when the type is a + // class type in C++. + if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() && + (!getLangOptions().CPlusPlus || + (!T->isDependentType() && !T->isRecordType()))) { + unsigned Quals = D.getDeclSpec().getTypeQualifiers(); + std::string QualStr; + unsigned NumQuals = 0; + SourceLocation Loc; + if (Quals & Qualifiers::Const) { + Loc = D.getDeclSpec().getConstSpecLoc(); + ++NumQuals; + QualStr = "const"; + } + if (Quals & Qualifiers::Volatile) { + if (NumQuals == 0) { + Loc = D.getDeclSpec().getVolatileSpecLoc(); + QualStr = "volatile"; + } else + QualStr += " volatile"; + ++NumQuals; + } + if (Quals & Qualifiers::Restrict) { + if (NumQuals == 0) { + Loc = D.getDeclSpec().getRestrictSpecLoc(); + QualStr = "restrict"; + } else + QualStr += " restrict"; + ++NumQuals; + } + assert(NumQuals > 0 && "No known qualifiers?"); + + SemaDiagnosticBuilder DB = Diag(Loc, diag::warn_qual_return_type); + DB << QualStr << NumQuals; + if (Quals & Qualifiers::Const) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getConstSpecLoc()); + if (Quals & Qualifiers::Volatile) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getVolatileSpecLoc()); + if (Quals & Qualifiers::Restrict) + DB << FixItHint::CreateRemoval(D.getDeclSpec().getRestrictSpecLoc()); + } + if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) { // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. @@ -1154,29 +1186,14 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) Diag(FTI.getThrowLoc(), diag::err_exception_spec_in_typedef); - if (FTI.NumArgs == 0) { - if (getLangOptions().CPlusPlus) { - // C++ 8.3.5p2: If the parameter-declaration-clause is empty, the - // function takes no arguments. - llvm::SmallVector<QualType, 4> Exceptions; - Exceptions.reserve(FTI.NumExceptions); - for (unsigned ei = 0, ee = FTI.NumExceptions; ei != ee; ++ei) { - // FIXME: Preserve type source info. - QualType ET = GetTypeFromParser(FTI.Exceptions[ei].Ty); - // Check that the type is valid for an exception spec, and drop it - // if not. - if (!CheckSpecifiedExceptionType(ET, FTI.Exceptions[ei].Range)) - Exceptions.push_back(ET); - } - T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, FTI.TypeQuals, - FTI.hasExceptionSpec, - FTI.hasAnyExceptionSpec, - Exceptions.size(), Exceptions.data(), - FunctionType::ExtInfo()); - } else if (FTI.isVariadic) { - // We allow a zero-parameter variadic function in C if the - // function is marked with the "overloadable" - // attribute. Scan for this attribute now. + if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { + // Simple void foo(), where the incoming T is the result type. + T = Context.getFunctionNoProtoType(T); + } else { + // We allow a zero-parameter variadic function in C if the + // function is marked with the "overloadable" attribute. Scan + // for this attribute now. + if (!FTI.NumArgs && FTI.isVariadic && !getLangOptions().CPlusPlus) { bool Overloadable = false; for (const AttributeList *Attrs = D.getAttributes(); Attrs; Attrs = Attrs->getNext()) { @@ -1188,21 +1205,20 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (!Overloadable) Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg); - T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic, 0, - false, false, 0, 0, - FunctionType::ExtInfo()); - } else { - // Simple void foo(), where the incoming T is the result type. - T = Context.getFunctionNoProtoType(T); } - } else if (FTI.ArgInfo[0].Param == 0) { - // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition. - Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); - D.setInvalidType(true); - } else { + + if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) { + // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function + // definition. + Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); + D.setInvalidType(true); + break; + } + // Otherwise, we have a function with an argument list that is // potentially variadic. llvm::SmallVector<QualType, 16> ArgTys; + ArgTys.reserve(FTI.NumArgs); for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = @@ -1278,13 +1294,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, break; } case DeclaratorChunk::MemberPointer: - // Verify that we're not building a pointer to pointer to function with - // exception specification. - if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { - Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); - D.setInvalidType(true); - // Build the type anyway. - } // The scope spec must refer to a class, or be dependent. QualType ClsType; if (DeclType.Mem.Scope().isInvalid()) { @@ -1323,11 +1332,12 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } if (!ClsType.isNull()) - T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals, - DeclType.Loc, D.getIdentifier()); + T = BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier()); if (T.isNull()) { T = Context.IntTy; D.setInvalidType(true); + } else if (DeclType.Mem.TypeQuals) { + T = BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals); } break; } @@ -1352,18 +1362,19 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // for a nonstatic member function, the function type to which a pointer // to member refers, or the top-level function type of a function typedef // declaration. + bool FreeFunction = (D.getContext() != Declarator::MemberContext && + (!D.getCXXScopeSpec().isSet() || + !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)->isRecord())); if (FnTy->getTypeQuals() != 0 && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - ((D.getContext() != Declarator::MemberContext && - (!D.getCXXScopeSpec().isSet() || - !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true) - ->isRecord())) || + (FreeFunction || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { if (D.isFunctionDeclarator()) Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type); else Diag(D.getIdentifierLoc(), - diag::err_invalid_qualified_typedef_function_type_use); + diag::err_invalid_qualified_typedef_function_type_use) + << FreeFunction; // Strip the cv-quals from the type. T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(), @@ -1372,6 +1383,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } } + // If there's a constexpr specifier, treat it as a top-level const. + if (D.getDeclSpec().isConstexprSpecified()) { + T.addConst(); + } + // Process any function attributes we might have delayed from the // declaration-specifiers. ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec); @@ -1386,14 +1402,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk); - if (TInfo) { - if (D.isInvalidType()) - *TInfo = 0; - else - *TInfo = GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); - } - - return T; + if (T.isNull()) + return Context.getNullTypeSourceInfo(); + else if (D.isInvalidType()) + return Context.getTrivialTypeSourceInfo(T); + return GetTypeSourceInfoForDeclarator(D, T, ReturnTypeInfo); } namespace { @@ -1527,6 +1540,28 @@ namespace { // FIXME: load appropriate source location. TL.setNameLoc(DS.getTypeSpecTypeLoc()); } + void VisitDependentTemplateSpecializationTypeLoc( + DependentTemplateSpecializationTypeLoc TL) { + ElaboratedTypeKeyword Keyword + = TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType()); + if (Keyword == ETK_Typename) { + TypeSourceInfo *TInfo = 0; + Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo); + if (TInfo) { + TL.copy(cast<DependentTemplateSpecializationTypeLoc>( + TInfo->getTypeLoc())); + return; + } + } + TL.initializeLocal(SourceLocation()); + TL.setKeywordLoc(Keyword != ETK_None + ? DS.getTypeSpecTypeLoc() + : SourceLocation()); + const CXXScopeSpec& SS = DS.getTypeSpecScope(); + TL.setQualifierRange(SS.isEmpty() ? SourceRange() : SS.getRange()); + // FIXME: load appropriate source location. + TL.setNameLoc(DS.getTypeSpecTypeLoc()); + } void VisitTypeLoc(TypeLoc TL) { // FIXME: add other typespec types and change this to an assert. @@ -1651,53 +1686,14 @@ void LocInfoType::getAsStringInternal(std::string &Str, " GetTypeFromParser"); } -/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that -/// may be similar (C++ 4.4), replaces T1 and T2 with the type that -/// they point to and return true. If T1 and T2 aren't pointer types -/// or pointer-to-member types, or if they are not similar at this -/// level, returns false and leaves T1 and T2 unchanged. Top-level -/// qualifiers on T1 and T2 are ignored. This function will typically -/// be called in a loop that successively "unwraps" pointer and -/// pointer-to-member types to compare them at each level. -bool Sema::UnwrapSimilarPointerTypes(QualType& T1, QualType& T2) { - const PointerType *T1PtrType = T1->getAs<PointerType>(), - *T2PtrType = T2->getAs<PointerType>(); - if (T1PtrType && T2PtrType) { - T1 = T1PtrType->getPointeeType(); - T2 = T2PtrType->getPointeeType(); - return true; - } - - const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), - *T2MPType = T2->getAs<MemberPointerType>(); - if (T1MPType && T2MPType && - Context.getCanonicalType(T1MPType->getClass()) == - Context.getCanonicalType(T2MPType->getClass())) { - T1 = T1MPType->getPointeeType(); - T2 = T2MPType->getPointeeType(); - return true; - } - - if (getLangOptions().ObjC1) { - const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(), - *T2OPType = T2->getAs<ObjCObjectPointerType>(); - if (T1OPType && T2OPType) { - T1 = T1OPType->getPointeeType(); - T2 = T2OPType->getPointeeType(); - return true; - } - } - return false; -} - Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // C99 6.7.6: Type names have no identifier. This is already validated by // the parser. assert(D.getIdentifier() == 0 && "Type name should have no identifier!"); - TypeSourceInfo *TInfo = 0; TagDecl *OwnedTag = 0; - QualType T = GetTypeForDeclarator(D, S, &TInfo, &OwnedTag); + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S, &OwnedTag); + QualType T = TInfo->getType(); if (D.isInvalidType()) return true; @@ -1714,9 +1710,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { << Context.getTypeDeclType(OwnedTag); } - if (TInfo) - T = CreateLocInfoType(T, TInfo); - + T = CreateLocInfoType(T, TInfo); return T.getAsOpaquePtr(); } @@ -1934,7 +1928,8 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { /// The raw attribute should contain precisely 1 argument, the vector size for /// the variable, measured in bytes. If curType and rawAttr are well formed, /// this routine will return a new vector type. -static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, Sema &S) { +static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, + Sema &S) { // Check the attribute arugments. if (Attr.getNumArgs() != 1) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; @@ -1977,7 +1972,8 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr, S // Success! Instantiate the vector type, the number of elements is > 0, and // not required to be a power of 2, unlike GCC. - CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false); + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, + VectorType::NotAltiVec); } void ProcessTypeAttributeList(Sema &S, QualType &Result, diff --git a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h index a18701e..17103c5 100644 --- a/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h +++ b/contrib/llvm/tools/clang/lib/Sema/TreeTransform.h @@ -442,7 +442,7 @@ public: /// By default, performs semantic analysis when building the vector type. /// Subclasses may override this routine to provide different behavior. QualType RebuildVectorType(QualType ElementType, unsigned NumElements, - bool IsAltiVec, bool IsPixel); + VectorType::AltiVecSpecific AltiVecSpec); /// \brief Build a new extended vector type given the element type and /// number of elements. @@ -533,16 +533,30 @@ public: /// By default, builds a new DependentNameType type from the /// nested-name-specifier and the given type. Subclasses may override /// this routine to provide different behavior. - QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType T) { - if (NNS->isDependent()) { - // If the name is still dependent, just build a new dependent name type. - CXXScopeSpec SS; - SS.setScopeRep(NNS); - if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(Keyword, NNS, - cast<TemplateSpecializationType>(T)); - } + QualType RebuildDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &Args) { + // Rebuild the template name. + // TODO: avoid TemplateName abstraction + TemplateName InstName = + getDerived().RebuildTemplateName(NNS, *Name, QualType()); + + if (InstName.isNull()) + return QualType(); + + // If it's still dependent, make a dependent specialization. + if (InstName.getAsDependentTemplateName()) + return SemaRef.Context.getDependentTemplateSpecializationType( + Keyword, NNS, Name, Args); + + // Otherwise, make an elaborated type wrapping a non-dependent + // specialization. + QualType T = + getDerived().RebuildTemplateSpecializationType(InstName, NameLoc, Args); + if (T.isNull()) return QualType(); return SemaRef.Context.getElaboratedType(Keyword, NNS, T); } @@ -1160,7 +1174,9 @@ public: SS.setScopeRep(Qualifier); } - QualType BaseType = ((Expr*) Base.get())->getType(); + Expr *BaseExpr = Base.takeAs<Expr>(); + getSema().DefaultFunctionArrayConversion(BaseExpr); + QualType BaseType = BaseExpr->getType(); // FIXME: this involves duplicating earlier analysis in a lot of // cases; we should avoid this when possible. @@ -1169,8 +1185,8 @@ public: R.addDecl(FoundDecl); R.resolveKind(); - return getSema().BuildMemberReferenceExpr(move(Base), BaseType, - OpLoc, isArrow, + return getSema().BuildMemberReferenceExpr(getSema().Owned(BaseExpr), + BaseType, OpLoc, isArrow, SS, FirstQualifierInScope, R, ExplicitTemplateArgs); } @@ -1561,7 +1577,7 @@ public: /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. - OwningExprResult RebuildCXXZeroInitValueExpr(SourceLocation TypeStartLoc, + OwningExprResult RebuildCXXScalarValueInitExpr(SourceLocation TypeStartLoc, SourceLocation LParenLoc, QualType T, SourceLocation RParenLoc) { @@ -1580,7 +1596,7 @@ public: SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - bool ParenTypeId, + SourceRange TypeIdParens, QualType AllocType, SourceLocation TypeLoc, SourceRange TypeRange, @@ -1592,7 +1608,7 @@ public: PlacementLParen, move(PlacementArgs), PlacementRParen, - ParenTypeId, + TypeIdParens, AllocType, TypeLoc, TypeRange, @@ -1815,7 +1831,8 @@ public: Sema::LookupMemberName); OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IvarLoc, - SS, DeclPtrTy()); + SS, DeclPtrTy(), + false); if (Result.isInvalid()) return getSema().ExprError(); @@ -1844,7 +1861,8 @@ public: bool IsArrow = false; OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/PropertyLoc, - SS, DeclPtrTy()); + SS, DeclPtrTy(), + false); if (Result.isInvalid()) return getSema().ExprError(); @@ -1892,7 +1910,8 @@ public: Sema::LookupMemberName); OwningExprResult Result = getSema().LookupMemberExpr(R, Base, IsArrow, /*FIME:*/IsaLoc, - SS, DeclPtrTy()); + SS, DeclPtrTy(), + false); if (Result.isInvalid()) return getSema().ExprError(); @@ -1933,7 +1952,7 @@ public: Expr **Subs = (Expr **)SubExprs.release(); CallExpr *TheCall = new (SemaRef.Context) CallExpr(SemaRef.Context, Callee, Subs, NumSubExprs, - Builtin->getResultType(), + Builtin->getCallResultType(), RParenLoc); OwningExprResult OwnedCall(SemaRef.Owned(TheCall)); @@ -2405,11 +2424,11 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, if (Result->isFunctionType() || Result->isReferenceType()) return Result; - Result = SemaRef.Context.getQualifiedType(Result, Quals); - - TLB.push<QualifiedTypeLoc>(Result); - - // No location information to preserve. + if (!Quals.empty()) { + Result = SemaRef.BuildQualifiedType(Result, T.getBeginLoc(), Quals); + TLB.push<QualifiedTypeLoc>(Result); + // No location information to preserve. + } return Result; } @@ -2792,7 +2811,7 @@ QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB, if (getDerived().AlwaysRebuild() || ElementType != T->getElementType()) { Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(), - T->isAltiVec(), T->isPixel()); + T->getAltiVecSpecific()); if (Result.isNull()) return QualType(); } @@ -3298,46 +3317,23 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, if (!NNS) return QualType(); - QualType Result; - - if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { - QualType NewTemplateId - = getDerived().TransformType(QualType(TemplateId, 0)); - if (NewTemplateId.isNull()) - return QualType(); - - if (!getDerived().AlwaysRebuild() && - NNS == T->getQualifier() && - NewTemplateId == QualType(TemplateId, 0)) - return QualType(T, 0); - - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - NewTemplateId); - } else { - Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, - T->getIdentifier(), - TL.getKeywordLoc(), - TL.getQualifierRange(), - TL.getNameLoc()); - } + QualType Result + = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, + T->getIdentifier(), + TL.getKeywordLoc(), + TL.getQualifierRange(), + TL.getNameLoc()); if (Result.isNull()) return QualType(); if (const ElaboratedType* ElabT = Result->getAs<ElaboratedType>()) { QualType NamedT = ElabT->getNamedType(); - if (isa<TemplateSpecializationType>(NamedT)) { - TemplateSpecializationTypeLoc NamedTLoc - = TLB.push<TemplateSpecializationTypeLoc>(NamedT); - // FIXME: fill locations - NamedTLoc.initializeLocal(TL.getNameLoc()); - } else { - TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); - } + TLB.pushTypeSpec(NamedT).setNameLoc(TL.getNameLoc()); + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); - } - else { + } else { DependentNameTypeLoc NewTL = TLB.push<DependentNameTypeLoc>(Result); NewTL.setKeywordLoc(TL.getKeywordLoc()); NewTL.setQualifierRange(TL.getQualifierRange()); @@ -3347,6 +3343,62 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, } template<typename Derived> +QualType TreeTransform<Derived>:: + TransformDependentTemplateSpecializationType(TypeLocBuilder &TLB, + DependentTemplateSpecializationTypeLoc TL, + QualType ObjectType) { + DependentTemplateSpecializationType *T = TL.getTypePtr(); + + NestedNameSpecifier *NNS + = getDerived().TransformNestedNameSpecifier(T->getQualifier(), + TL.getQualifierRange(), + ObjectType); + if (!NNS) + return QualType(); + + TemplateArgumentListInfo NewTemplateArgs; + NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); + NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); + + for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) { + TemplateArgumentLoc Loc; + if (getDerived().TransformTemplateArgument(TL.getArgLoc(I), Loc)) + return QualType(); + NewTemplateArgs.addArgument(Loc); + } + + QualType Result = getDerived().RebuildDependentTemplateSpecializationType( + T->getKeyword(), + NNS, + T->getIdentifier(), + TL.getNameLoc(), + NewTemplateArgs); + if (Result.isNull()) + return QualType(); + + if (const ElaboratedType *ElabT = dyn_cast<ElaboratedType>(Result)) { + QualType NamedT = ElabT->getNamedType(); + + // Copy information relevant to the template specialization. + TemplateSpecializationTypeLoc NamedTL + = TLB.push<TemplateSpecializationTypeLoc>(NamedT); + NamedTL.setLAngleLoc(TL.getLAngleLoc()); + NamedTL.setRAngleLoc(TL.getRAngleLoc()); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) + NamedTL.setArgLocInfo(I, TL.getArgLocInfo(I)); + + // Copy information relevant to the elaborated type. + ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); + NewTL.setKeywordLoc(TL.getKeywordLoc()); + NewTL.setQualifierRange(TL.getQualifierRange()); + } else { + TypeLoc NewTL(Result, TL.getOpaqueData()); + TLB.pushFullCopy(NewTL); + } + return Result; +} + +template<typename Derived> QualType TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB, ObjCInterfaceTypeLoc TL, @@ -5167,7 +5219,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { +TreeTransform<Derived>::TransformCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { TemporaryBase Rebase(*this, E->getTypeBeginLoc(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); @@ -5178,10 +5230,10 @@ TreeTransform<Derived>::TransformCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { T == E->getType()) return SemaRef.Owned(E->Retain()); - return getDerived().RebuildCXXZeroInitValueExpr(E->getTypeBeginLoc(), - /*FIXME:*/E->getTypeBeginLoc(), - T, - E->getRParenLoc()); + return getDerived().RebuildCXXScalarValueInitExpr(E->getTypeBeginLoc(), + /*FIXME:*/E->getTypeBeginLoc(), + T, + E->getRParenLoc()); } template<typename Derived> @@ -5300,7 +5352,7 @@ TreeTransform<Derived>::TransformCXXNewExpr(CXXNewExpr *E) { /*FIXME:*/E->getLocStart(), move_arg(PlacementArgs), /*FIXME:*/E->getLocStart(), - E->isParenTypeId(), + E->getTypeIdParens(), AllocType, /*FIXME:*/E->getLocStart(), /*FIXME:*/SourceRange(), @@ -6165,17 +6217,75 @@ TreeTransform<Derived>::TransformShuffleVectorExpr(ShuffleVectorExpr *E) { template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformBlockExpr(BlockExpr *E) { - // FIXME: Implement this! - assert(false && "Cannot transform block expressions yet"); - return SemaRef.Owned(E->Retain()); + SourceLocation CaretLoc(E->getExprLoc()); + + SemaRef.ActOnBlockStart(CaretLoc, /*Scope=*/0); + BlockScopeInfo *CurBlock = SemaRef.getCurBlock(); + CurBlock->TheDecl->setIsVariadic(E->getBlockDecl()->isVariadic()); + llvm::SmallVector<ParmVarDecl*, 4> Params; + llvm::SmallVector<QualType, 4> ParamTypes; + + // Parameter substitution. + const BlockDecl *BD = E->getBlockDecl(); + for (BlockDecl::param_const_iterator P = BD->param_begin(), + EN = BD->param_end(); P != EN; ++P) { + ParmVarDecl *OldParm = (*P); + ParmVarDecl *NewParm = getDerived().TransformFunctionTypeParam(OldParm); + QualType NewType = NewParm->getType(); + Params.push_back(NewParm); + ParamTypes.push_back(NewParm->getType()); + } + + const FunctionType *BExprFunctionType = E->getFunctionType(); + QualType BExprResultType = BExprFunctionType->getResultType(); + if (!BExprResultType.isNull()) { + if (!BExprResultType->isDependentType()) + CurBlock->ReturnType = BExprResultType; + else if (BExprResultType != SemaRef.Context.DependentTy) + CurBlock->ReturnType = getDerived().TransformType(BExprResultType); + } + + // Transform the body + OwningStmtResult Body = getDerived().TransformStmt(E->getBody()); + if (Body.isInvalid()) + return SemaRef.ExprError(); + // Set the parameters on the block decl. + if (!Params.empty()) + CurBlock->TheDecl->setParams(Params.data(), Params.size()); + + QualType FunctionType = getDerived().RebuildFunctionProtoType( + CurBlock->ReturnType, + ParamTypes.data(), + ParamTypes.size(), + BD->isVariadic(), + 0); + + CurBlock->FunctionType = FunctionType; + return SemaRef.ActOnBlockStmtExpr(CaretLoc, move(Body), /*Scope=*/0); } template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { - // FIXME: Implement this! - assert(false && "Cannot transform block-related expressions yet"); - return SemaRef.Owned(E->Retain()); + NestedNameSpecifier *Qualifier = 0; + + ValueDecl *ND + = cast_or_null<ValueDecl>(getDerived().TransformDecl(E->getLocation(), + E->getDecl())); + if (!ND) + return SemaRef.ExprError(); + + if (!getDerived().AlwaysRebuild() && + ND == E->getDecl()) { + // Mark it referenced in the new context regardless. + // FIXME: this is a bit instantiation-specific. + SemaRef.MarkDeclarationReferenced(E->getLocation(), ND); + + return SemaRef.Owned(E->Retain()); + } + + return getDerived().RebuildDeclRefExpr(Qualifier, SourceLocation(), + ND, E->getLocation(), 0); } //===----------------------------------------------------------------------===// @@ -6185,14 +6295,14 @@ TreeTransform<Derived>::TransformBlockDeclRefExpr(BlockDeclRefExpr *E) { template<typename Derived> QualType TreeTransform<Derived>::RebuildPointerType(QualType PointeeType, SourceLocation Star) { - return SemaRef.BuildPointerType(PointeeType, Qualifiers(), Star, + return SemaRef.BuildPointerType(PointeeType, Star, getDerived().getBaseEntity()); } template<typename Derived> QualType TreeTransform<Derived>::RebuildBlockPointerType(QualType PointeeType, SourceLocation Star) { - return SemaRef.BuildBlockPointerType(PointeeType, Qualifiers(), Star, + return SemaRef.BuildBlockPointerType(PointeeType, Star, getDerived().getBaseEntity()); } @@ -6201,7 +6311,7 @@ QualType TreeTransform<Derived>::RebuildReferenceType(QualType ReferentType, bool WrittenAsLValue, SourceLocation Sigil) { - return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Qualifiers(), + return SemaRef.BuildReferenceType(ReferentType, WrittenAsLValue, Sigil, getDerived().getBaseEntity()); } @@ -6210,7 +6320,7 @@ QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType, QualType ClassType, SourceLocation Sigil) { - return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Qualifiers(), + return SemaRef.BuildMemberPointerType(PointeeType, ClassType, Sigil, getDerived().getBaseEntity()); } @@ -6293,11 +6403,10 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType, template<typename Derived> QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType, - unsigned NumElements, - bool IsAltiVec, bool IsPixel) { + unsigned NumElements, + VectorType::AltiVecSpecific AltiVecSpec) { // FIXME: semantic checking! - return SemaRef.Context.getVectorType(ElementType, NumElements, - IsAltiVec, IsPixel); + return SemaRef.Context.getVectorType(ElementType, NumElements, AltiVecSpec); } template<typename Derived> @@ -6449,13 +6558,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, SS.setScopeRep(Qualifier); UnqualifiedId Name; Name.setIdentifier(&II, /*FIXME:*/getDerived().getBaseLocation()); - return getSema().ActOnDependentTemplateName( - /*FIXME:*/getDerived().getBaseLocation(), - SS, - Name, - ObjectType.getAsOpaquePtr(), - /*EnteringContext=*/false) - .template getAsVal<TemplateName>(); + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, + /*FIXME:*/getDerived().getBaseLocation(), + SS, + Name, + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false, + Template); + return Template.template getAsVal<TemplateName>(); } template<typename Derived> @@ -6470,13 +6581,15 @@ TreeTransform<Derived>::RebuildTemplateName(NestedNameSpecifier *Qualifier, SourceLocation SymbolLocations[3]; // FIXME: Bogus location information. Name.setOperatorFunctionId(/*FIXME:*/getDerived().getBaseLocation(), Operator, SymbolLocations); - return getSema().ActOnDependentTemplateName( + Sema::TemplateTy Template; + getSema().ActOnDependentTemplateName(/*Scope=*/0, /*FIXME:*/getDerived().getBaseLocation(), - SS, - Name, - ObjectType.getAsOpaquePtr(), - /*EnteringContext=*/false) - .template getAsVal<TemplateName>(); + SS, + Name, + ObjectType.getAsOpaquePtr(), + /*EnteringContext=*/false, + Template); + return Template.template getAsVal<TemplateName>(); } template<typename Derived> |