diff options
Diffstat (limited to 'lib/Sema')
31 files changed, 4717 insertions, 2736 deletions
diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index bff4751..b09526e 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -14,8 +14,6 @@ #include "IdentifierResolver.h" #include "clang/Basic/LangOptions.h" -#include <list> -#include <vector> using namespace clang; @@ -27,14 +25,31 @@ using namespace clang; /// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each /// individual IdDeclInfo to heap. class IdentifierResolver::IdDeclInfoMap { - static const unsigned int VECTOR_SIZE = 512; - // Holds vectors of IdDeclInfos that serve as 'pools'. - // New vectors are added when the current one is full. - std::list< std::vector<IdDeclInfo> > IDIVecs; + static const unsigned int POOL_SIZE = 512; + + /// We use our own linked-list implementation because it is sadly + /// impossible to add something to a pre-C++0x STL container without + /// a completely unnecessary copy. + struct IdDeclInfoPool { + IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {} + + IdDeclInfoPool *Next; + IdDeclInfo Pool[POOL_SIZE]; + }; + + IdDeclInfoPool *CurPool; unsigned int CurIndex; public: - IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {} + IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {} + + ~IdDeclInfoMap() { + IdDeclInfoPool *Cur = CurPool; + while (IdDeclInfoPool *P = Cur) { + Cur = Cur->Next; + delete P; + } + } /// Returns the IdDeclInfo associated to the DeclarationName. /// It creates a new IdDeclInfo if one was not created before for this id. @@ -235,14 +250,11 @@ IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) { if (Ptr) return *toIdDeclInfo(Ptr); - if (CurIndex == VECTOR_SIZE) { - // Add a IdDeclInfo vector 'pool' - IDIVecs.push_back(std::vector<IdDeclInfo>()); - // Fill the vector - IDIVecs.back().resize(VECTOR_SIZE); + if (CurIndex == POOL_SIZE) { + CurPool = new IdDeclInfoPool(CurPool); CurIndex = 0; } - IdDeclInfo *IDI = &IDIVecs.back()[CurIndex]; + IdDeclInfo *IDI = &CurPool->Pool[CurIndex]; Name.setFETokenInfo(reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(IDI) | 0x1) ); diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h index f4cea2e..6b26945 100644 --- a/lib/Sema/Lookup.h +++ b/lib/Sema/Lookup.h @@ -224,6 +224,10 @@ public: return Ambiguity; } + const UnresolvedSetImpl &asUnresolvedSet() const { + return Decls; + } + iterator begin() const { return iterator(Decls.begin()); } iterator end() const { return iterator(Decls.end()); } @@ -499,7 +503,7 @@ private: if (isAmbiguous()) SemaRef.DiagnoseAmbiguousLookup(*this); else if (isClassLookup() && SemaRef.getLangOptions().AccessControl) - SemaRef.CheckAccess(*this); + SemaRef.CheckLookupAccess(*this); } void setAmbiguous(AmbiguityKind AK) { @@ -583,6 +587,44 @@ private: virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) = 0; }; + +/// \brief A class for storing results from argument-dependent lookup. +class ADLResult { +private: + /// A map from canonical decls to the 'most recent' decl. + llvm::DenseMap<NamedDecl*, NamedDecl*> Decls; + +public: + /// Adds a new ADL candidate to this map. + void insert(NamedDecl *D); + + /// Removes any data associated with a given decl. + void erase(NamedDecl *D) { + Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); + } + + class iterator { + typedef llvm::DenseMap<NamedDecl*,NamedDecl*>::iterator inner_iterator; + inner_iterator iter; + + friend class ADLResult; + iterator(const inner_iterator &iter) : iter(iter) {} + public: + iterator() {} + + iterator &operator++() { ++iter; return *this; } + iterator operator++(int) { return iterator(iter++); } + + NamedDecl *operator*() const { return iter->second; } + + bool operator==(const iterator &other) const { return iter == other.iter; } + bool operator!=(const iterator &other) const { return iter != other.iter; } + }; + + iterator begin() { return iterator(Decls.begin()); } + iterator end() { return iterator(Decls.end()); } +}; + } #endif diff --git a/lib/Sema/Makefile b/lib/Sema/Makefile index 0f4c796..158f1af 100644 --- a/lib/Sema/Makefile +++ b/lib/Sema/Makefile @@ -15,7 +15,6 @@ LEVEL = ../../../.. LIBRARYNAME := clangSema BUILD_ARCHIVE = 1 -CXXFLAGS = -fno-rtti CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 171101b..38c842e 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -15,260 +15,18 @@ #include "Sema.h" #include "TargetAttributesSema.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/APFloat.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/Lex/Preprocessor.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" using namespace clang; - -/// Determines whether we should have an a.k.a. clause when -/// pretty-printing a type. There are three main criteria: -/// -/// 1) Some types provide very minimal sugar that doesn't impede the -/// user's understanding --- for example, elaborated type -/// specifiers. If this is all the sugar we see, we don't want an -/// a.k.a. clause. -/// 2) Some types are technically sugared but are much more familiar -/// when seen in their sugared form --- for example, va_list, -/// vector types, and the magic Objective C types. We don't -/// want to desugar these, even if we do produce an a.k.a. clause. -/// 3) Some types may have already been desugared previously in this diagnostic. -/// if this is the case, doing another "aka" would just be clutter. -/// -static bool ShouldAKA(ASTContext &Context, QualType QT, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - QualType &DesugaredQT) { - QualType InputTy = QT; - - bool AKA = false; - QualifierCollector Qc; - - while (true) { - const Type *Ty = Qc.strip(QT); - - // Don't aka just because we saw an elaborated type... - if (isa<ElaboratedType>(Ty)) { - QT = cast<ElaboratedType>(Ty)->desugar(); - continue; - } - - // ...or a qualified name type... - if (isa<QualifiedNameType>(Ty)) { - QT = cast<QualifiedNameType>(Ty)->desugar(); - continue; - } - - // ...or a substituted template type parameter. - if (isa<SubstTemplateTypeParmType>(Ty)) { - QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); - continue; - } - - // Don't desugar template specializations. - if (isa<TemplateSpecializationType>(Ty)) - break; - - // Don't desugar magic Objective-C types. - if (QualType(Ty,0) == Context.getObjCIdType() || - QualType(Ty,0) == Context.getObjCClassType() || - QualType(Ty,0) == Context.getObjCSelType() || - QualType(Ty,0) == Context.getObjCProtoType()) - break; - - // Don't desugar va_list. - if (QualType(Ty,0) == Context.getBuiltinVaListType()) - break; - - // Otherwise, do a single-step desugar. - QualType Underlying; - bool IsSugar = false; - switch (Ty->getTypeClass()) { -#define ABSTRACT_TYPE(Class, Base) -#define TYPE(Class, Base) \ - case Type::Class: { \ - const Class##Type *CTy = cast<Class##Type>(Ty); \ - if (CTy->isSugared()) { \ - IsSugar = true; \ - Underlying = CTy->desugar(); \ - } \ - break; \ - } -#include "clang/AST/TypeNodes.def" - } - - // If it wasn't sugared, we're done. - if (!IsSugar) - break; - - // If the desugared type is a vector type, we don't want to expand - // it, it will turn into an attribute mess. People want their "vec4". - if (isa<VectorType>(Underlying)) - break; - - // Don't desugar through the primary typedef of an anonymous type. - if (isa<TagType>(Underlying) && isa<TypedefType>(QT)) - if (cast<TagType>(Underlying)->getDecl()->getTypedefForAnonDecl() == - cast<TypedefType>(QT)->getDecl()) - break; - - // Otherwise, we're tearing through something opaque; note that - // we'll eventually need an a.k.a. clause and keep going. - AKA = true; - QT = Underlying; - continue; - } - - // If we never tore through opaque sugar, don't print aka. - if (!AKA) return false; - - // If we did, check to see if we already desugared this type in this - // diagnostic. If so, don't do it again. - for (unsigned i = 0; i != NumPrevArgs; ++i) { - // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == Diagnostic::ak_qualtype) { - void *Ptr = (void*)PrevArgs[i].second; - QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); - if (PrevTy == InputTy) - return false; - } - } - - DesugaredQT = Qc.apply(QT); - return true; -} - -/// \brief Convert the given type to a string suitable for printing as part of -/// a diagnostic. -/// -/// \param Context the context in which the type was allocated -/// \param Ty the type to print -static std::string -ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs) { - // FIXME: Playing with std::string is really slow. - std::string S = Ty.getAsString(Context.PrintingPolicy); - - // Consider producing an a.k.a. clause if removing all the direct - // sugar gives us something "significantly different". - - QualType DesugaredTy; - if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) { - S = "'"+S+"' (aka '"; - S += DesugaredTy.getAsString(Context.PrintingPolicy); - S += "')"; - return S; - } - - S = "'" + S + "'"; - return S; -} -/// ConvertQualTypeToStringFn - This function is used to pretty print the -/// specified QualType as a string in diagnostics. -static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val, - const char *Modifier, unsigned ModLen, - const char *Argument, unsigned ArgLen, - const Diagnostic::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - llvm::SmallVectorImpl<char> &Output, - void *Cookie) { - ASTContext &Context = *static_cast<ASTContext*>(Cookie); - - std::string S; - bool NeedQuotes = true; - - switch (Kind) { - default: assert(0 && "unknown ArgumentKind"); - case Diagnostic::ak_qualtype: { - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for QualType argument"); - - QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs); - NeedQuotes = false; - break; - } - case Diagnostic::ak_declarationname: { - DeclarationName N = DeclarationName::getFromOpaqueInteger(Val); - S = N.getAsString(); - - if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) - S = '+' + S; - else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) && ArgLen==0) - S = '-' + S; - else - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for DeclarationName argument"); - break; - } - case Diagnostic::ak_nameddecl: { - bool Qualified; - if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) - Qualified = true; - else { - assert(ModLen == 0 && ArgLen == 0 && - "Invalid modifier for NamedDecl* argument"); - Qualified = false; - } - reinterpret_cast<NamedDecl*>(Val)-> - getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); - break; - } - case Diagnostic::ak_nestednamespec: { - llvm::raw_string_ostream OS(S); - reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, - Context.PrintingPolicy); - NeedQuotes = false; - break; - } - case Diagnostic::ak_declcontext: { - DeclContext *DC = reinterpret_cast<DeclContext *> (Val); - assert(DC && "Should never have a null declaration context"); - - if (DC->isTranslationUnit()) { - // FIXME: Get these strings from some localized place - if (Context.getLangOptions().CPlusPlus) - S = "the global namespace"; - else - S = "the global scope"; - } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { - S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs); - } else { - // FIXME: Get these strings from some localized place - NamedDecl *ND = cast<NamedDecl>(DC); - if (isa<NamespaceDecl>(ND)) - S += "namespace "; - else if (isa<ObjCMethodDecl>(ND)) - S += "method "; - else if (isa<FunctionDecl>(ND)) - S += "function "; - - S += "'"; - ND->getNameForDiagnostic(S, Context.PrintingPolicy, true); - S += "'"; - } - NeedQuotes = false; - break; - } - } - - if (NeedQuotes) - Output.push_back('\''); - - Output.append(S.begin(), S.end()); - - if (NeedQuotes) - Output.push_back('\''); -} - - static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) { if (C.getLangOptions().CPlusPlus) return CXXRecordDecl::Create(C, TagDecl::TK_struct, @@ -363,14 +121,15 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, GlobalNewDeleteDeclared(false), CompleteTranslationUnit(CompleteTranslationUnit), NumSFINAEErrors(0), NonInstantiationEntries(0), - CurrentInstantiationScope(0) + CurrentInstantiationScope(0), TyposCorrected(0) { TUScope = 0; if (getLangOptions().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); // Tell diagnostics how to render things from the AST library. - PP.getDiagnostics().SetArgToStringFn(ConvertArgToStringFn, &Context); + PP.getDiagnostics().SetArgToStringFn(&FormatASTNodeDiagnosticArgument, + &Context); ExprEvalContexts.push_back( ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0)); @@ -426,6 +185,12 @@ void Sema::DeleteStmt(StmtTy *S) { /// popped. 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)), + UnusedStaticFuncs.end()); + while (1) { // C++: Perform implicit template instantiations. // @@ -472,12 +237,14 @@ void Sema::ActOnEndOfTranslationUnit() { // translation unit contains a file scope declaration of that // identifier, with the composite type as of the end of the // translation unit, with an initializer equal to 0. - for (unsigned i = 0, e = TentativeDefinitionList.size(); i != e; ++i) { - VarDecl *VD = TentativeDefinitions.lookup(TentativeDefinitionList[i]); - - // If the tentative definition was completed, it will be in the list, but - // not the map. - if (VD == 0 || VD->isInvalidDecl() || !VD->isTentativeDefinition(Context)) + llvm::SmallSet<VarDecl *, 32> Seen; + for (unsigned i = 0, e = TentativeDefinitions.size(); i != e; ++i) { + VarDecl *VD = TentativeDefinitions[i]->getActingDefinition(); + + // If the tentative definition was completed, getActingDefinition() returns + // null. If we've already seen this variable before, insert()'s second + // return value is false. + if (VD == 0 || VD->isInvalidDecl() || !Seen.insert(VD)) continue; if (const IncompleteArrayType *ArrayT @@ -504,6 +271,15 @@ void Sema::ActOnEndOfTranslationUnit() { Consumer.CompleteTentativeDefinition(VD); } + + // Output warning for unused functions. + for (std::vector<FunctionDecl*>::iterator + F = UnusedStaticFuncs.begin(), + FEnd = UnusedStaticFuncs.end(); + F != FEnd; + ++F) + Diag((*F)->getLocation(), diag::warn_unused_function) << (*F)->getDeclName(); + } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 06e9e3a..3c7492a 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -60,6 +60,7 @@ namespace clang { class CallExpr; class DeclRefExpr; class UnresolvedLookupExpr; + class UnresolvedMemberExpr; class VarDecl; class ParmVarDecl; class TypedefDecl; @@ -95,6 +96,7 @@ namespace clang { class ObjCPropertyDecl; class ObjCContainerDecl; class FunctionProtoType; + class CXXBasePath; class CXXBasePaths; class CXXTemporary; class LookupResult; @@ -103,6 +105,7 @@ namespace clang { class InitializationSequence; class VisibleDeclConsumer; class TargetAttributesSema; + class ADLResult; /// BlockSemaInfo - When a block is being parsed, this contains information /// about the block. It is pointed to from Sema::CurBlock. @@ -150,7 +153,7 @@ class LocInfoType : public Type { enum { // The last number that can fit in Type's TC. // Avoids conflict with an existing Type class. - LocInfo = (1 << TypeClassBitSize) - 1 + LocInfo = Type::TypeLast + 1 }; TypeSourceInfo *DeclInfo; @@ -270,18 +273,124 @@ public: /// not visible. llvm::DenseMap<DeclarationName, NamedDecl *> LocallyScopedExternalDecls; - /// \brief The set of tentative declarations seen so far in this - /// translation unit for which no definition has been seen. - /// - /// The tentative declarations are indexed by the name of the - /// declaration, and only the most recent tentative declaration for - /// a given variable will be recorded here. - llvm::DenseMap<DeclarationName, VarDecl *> TentativeDefinitions; - std::vector<DeclarationName> TentativeDefinitionList; + /// \brief All the tentative definitions encountered in the TU. + std::vector<VarDecl *> TentativeDefinitions; + + /// \brief The set of static functions seen so far that have not been used. + std::vector<FunctionDecl*> UnusedStaticFuncs; + + /// An enum describing the kind of diagnostics to use when checking + /// access. + enum AccessDiagnosticsKind { + /// Suppress diagnostics. + ADK_quiet, + + /// Use the normal diagnostics. + ADK_normal, + + /// Use the diagnostics appropriate for checking a covariant + /// return type. + ADK_covariance + }; + + class AccessedEntity { + public: + enum Kind { + /// A member declaration found through lookup. The target is the + /// member. + Member, + + /// A base-to-derived conversion. The target is the base class. + BaseToDerivedConversion, + + /// A derived-to-base conversion. The target is the base class. + DerivedToBaseConversion + }; + + bool isMemberAccess() const { return K == Member; } + + static AccessedEntity makeMember(CXXRecordDecl *NamingClass, + AccessSpecifier Access, + NamedDecl *Target) { + AccessedEntity E; + E.K = Member; + E.Access = Access; + E.Target = Target; + E.NamingClass = NamingClass; + return E; + } + + static AccessedEntity makeBaseClass(bool BaseToDerived, + CXXRecordDecl *BaseClass, + CXXRecordDecl *DerivedClass, + AccessSpecifier Access) { + AccessedEntity E; + E.K = BaseToDerived ? BaseToDerivedConversion : DerivedToBaseConversion; + E.Access = Access; + E.Target = BaseClass; + E.NamingClass = DerivedClass; + return E; + } + + Kind getKind() const { return Kind(K); } + AccessSpecifier getAccess() const { return AccessSpecifier(Access); } + + // These apply to member decls... + NamedDecl *getTargetDecl() const { return Target; } + CXXRecordDecl *getNamingClass() const { return NamingClass; } + + // ...and these apply to hierarchy conversions. + CXXRecordDecl *getBaseClass() const { return cast<CXXRecordDecl>(Target); } + CXXRecordDecl *getDerivedClass() const { return NamingClass; } + + private: + unsigned K : 2; + unsigned Access : 2; + NamedDecl *Target; + CXXRecordDecl *NamingClass; + }; - /// \brief The collection of delayed deprecation warnings. - llvm::SmallVector<std::pair<SourceLocation,NamedDecl*>, 8> - DelayedDeprecationWarnings; + struct DelayedDiagnostic { + enum DDKind { Deprecation, Access }; + + unsigned char Kind; // actually a DDKind + bool Triggered; + + SourceLocation Loc; + + union { + /// Deprecation. + struct { NamedDecl *Decl; } DeprecationData; + + /// Access control. + AccessedEntity AccessData; + }; + + static DelayedDiagnostic makeDeprecation(SourceLocation Loc, + NamedDecl *D) { + DelayedDiagnostic DD; + DD.Kind = Deprecation; + DD.Triggered = false; + DD.Loc = Loc; + DD.DeprecationData.Decl = D; + return DD; + } + + static DelayedDiagnostic makeAccess(SourceLocation Loc, + const AccessedEntity &Entity) { + DelayedDiagnostic DD; + DD.Kind = Access; + DD.Triggered = false; + DD.Loc = Loc; + DD.AccessData = Entity; + return DD; + } + + }; + + /// \brief The stack of diagnostics that were delayed due to being + /// produced during the parsing of a declaration. + llvm::SmallVector<DelayedDiagnostic, 8> DelayedDiagnostics; /// \brief The depth of the current ParsingDeclaration stack. /// If nonzero, we are currently parsing a declaration (and @@ -517,8 +626,8 @@ public: //===--------------------------------------------------------------------===// // Type Analysis / Processing: SemaType.cpp. // + QualType adjustParameterType(QualType T); - void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL); QualType BuildPointerType(QualType T, unsigned Quals, SourceLocation Loc, DeclarationName Entity); QualType BuildReferenceType(QualType T, bool LValueRef, unsigned Quals, @@ -548,13 +657,15 @@ public: static QualType GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo = 0); bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); + bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); bool CheckEquivalentExceptionSpec( const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc); bool CheckEquivalentExceptionSpec( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc); + const FunctionProtoType *New, SourceLocation NewLoc, + bool *MissingEmptyExceptionSpecification = 0); bool CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Superset, SourceLocation SuperLoc, @@ -634,6 +745,7 @@ public: bool &OverloadableAttrRequired); void CheckMain(FunctionDecl *FD); virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D); + virtual void ActOnObjCCatchParam(DeclPtrTy D); virtual void ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc, ExprArg defarg); @@ -950,31 +1062,38 @@ public: // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. typedef llvm::SmallPtrSet<DeclContext *, 16> AssociatedNamespaceSet; - - typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet; typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; + void AddOverloadCandidate(NamedDecl *Function, + AccessSpecifier Access, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet &CandidateSet); + void AddOverloadCandidate(FunctionDecl *Function, + AccessSpecifier Access, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false, bool PartialOverloading = false); - void AddFunctionCandidates(const FunctionSet &Functions, + void AddFunctionCandidates(const UnresolvedSetImpl &Functions, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); - void AddMethodCandidate(NamedDecl *Decl, - QualType ObjectType, Expr **Args, unsigned NumArgs, + void AddMethodCandidate(NamedDecl *Decl, AccessSpecifier Access, + QualType ObjectType, + Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversion = false, bool ForceRValue = false); - void AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext, - QualType ObjectType, Expr **Args, unsigned NumArgs, + void AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false); void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + AccessSpecifier Access, CXXRecordDecl *ActingContext, const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, @@ -983,20 +1102,24 @@ public: bool SuppressUserConversions = false, bool ForceRValue = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + AccessSpecifier Access, const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, bool ForceRValue = false); void AddConversionCandidate(CXXConversionDecl *Conversion, + AccessSpecifier Access, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet); void AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + AccessSpecifier Access, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet); void AddSurrogateCandidate(CXXConversionDecl *Conversion, + AccessSpecifier Access, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, QualType ObjectTy, Expr **Args, unsigned NumArgs, @@ -1021,12 +1144,14 @@ public: Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet); void AddArgumentDependentLookupCandidates(DeclarationName Name, + bool Operator, Expr **Args, unsigned NumArgs, const TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading = false); bool isBetterOverloadCandidate(const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2); + const OverloadCandidate& Cand2, + SourceLocation Loc); OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, SourceLocation Loc, OverloadCandidateSet::iterator& Best); @@ -1072,12 +1197,12 @@ public: OwningExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned Opc, - FunctionSet &Functions, + const UnresolvedSetImpl &Fns, ExprArg input); OwningExprResult CreateOverloadedBinOp(SourceLocation OpLoc, unsigned Opc, - FunctionSet &Functions, + const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS); OwningExprResult CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, @@ -1217,16 +1342,15 @@ public: bool LookupParsedName(LookupResult &R, Scope *S, const CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); - ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, - FunctionSet &Functions); + UnresolvedSetImpl &Functions); void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - FunctionSet &Functions); + ADLResult &Functions); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer); @@ -1302,6 +1426,14 @@ public: void CollectImmediateProperties(ObjCContainerDecl *CDecl, llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap); + /// LookupPropertyDecl - Looks up a property in the current class and all + /// its protocols. + ObjCPropertyDecl *LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II); + + ObjCIvarDecl *SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl, + IdentifierInfo *NameII); + /// AtomicPropertySetterGetterRules - This routine enforces the rule (via /// warning) when atomic property has one but not the other user-declared /// setter or getter. @@ -1373,6 +1505,8 @@ public: SourceLocation ElseLoc, StmtArg ElseVal); virtual OwningStmtResult ActOnStartOfSwitchStmt(FullExprArg Cond, DeclPtrTy CondVar); + virtual void ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body); virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body); virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, @@ -1416,7 +1550,7 @@ public: bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, - std::string *Names, + IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, ExprArg AsmString, @@ -1466,6 +1600,8 @@ public: void PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy D); void EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc); + void HandleDelayedDeprecationCheck(DelayedDiagnostic &DD, Decl *Ctx); + //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. @@ -1770,7 +1906,8 @@ public: // Act on C++ namespaces virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, IdentifierInfo *Ident, - SourceLocation LBrace); + SourceLocation LBrace, + AttributeList *AttrList); virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace); virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, @@ -1847,7 +1984,8 @@ public: QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, - bool RequiresZeroInit = false); + bool RequiresZeroInit = false, + bool BaseInitialization = false); // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? @@ -1856,13 +1994,8 @@ public: CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, - bool RequiresZeroInit = false); - - OwningExprResult BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Cons, - QualType writtenTy, - SourceLocation tyBeginLoc, - MultiExprArg Args, - SourceLocation rParenLoc); + bool RequiresZeroInit = false, + bool BaseInitialization = false); OwningExprResult BuildCXXCastArgument(SourceLocation CastLoc, QualType Ty, @@ -1878,7 +2011,7 @@ public: /// FinalizeVarWithDestructor - Prepare for calling destructor on the /// constructed variable. - void FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType); + void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. @@ -1917,14 +2050,6 @@ public: Expr **Args, unsigned NumArgs, SourceLocation Loc, InitializationKind Kind); - - CXXConstructorDecl * - PerformInitializationByConstructor(QualType ClassType, - MultiExprArg ArgsPtr, - SourceLocation Loc, SourceRange Range, - DeclarationName InitEntity, - InitializationKind Kind, - ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs); bool CompleteConstructorCall(CXXConstructorDecl *Constructor, MultiExprArg ArgsPtr, @@ -2218,9 +2343,10 @@ public: CXXRecordDecl *ClassDecl); bool SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers, - bool IsImplicitConstructor); + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, + bool IsImplicitConstructor, + bool AnyErrors); /// MarkBaseAndMemberDestructorsReferenced - Given a destructor decl, /// mark all its non-trivial member and base destructor declarations @@ -2252,7 +2378,8 @@ public: virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, - MemInitTy **MemInits, unsigned NumMemInits); + MemInitTy **MemInits, unsigned NumMemInits, + bool AnyErrors); void CheckCompletedCXXClass(CXXRecordDecl *Record); virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, @@ -2326,7 +2453,7 @@ public: SourceLocation Loc, SourceRange Range, bool IgnoreAccess = false); bool CheckDerivedToBaseConversion(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, + AccessDiagnosticsKind ADK, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name); @@ -2353,22 +2480,43 @@ public: // C++ Access Control // + enum AccessResult { + AR_accessible, + AR_inaccessible, + AR_dependent, + AR_delayed + }; + bool SetMemberAccessSpecifier(NamedDecl *MemberDecl, NamedDecl *PrevMemberDecl, AccessSpecifier LexicalAS); - const CXXBaseSpecifier *FindInaccessibleBase(QualType Derived, QualType Base, - CXXBasePaths &Paths, - bool NoPrivileges = false); - - void CheckAccess(const LookupResult &R); - bool CheckAccess(const LookupResult &R, NamedDecl *D, AccessSpecifier Access); - - bool CheckBaseClassAccess(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, - CXXBasePaths& Paths, SourceLocation AccessLoc, - DeclarationName Name); - + AccessResult CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + NamedDecl *D, + AccessSpecifier Access); + AccessResult CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + NamedDecl *D, + AccessSpecifier Access); + AccessResult CheckConstructorAccess(SourceLocation Loc, + CXXConstructorDecl *D, + AccessSpecifier Access); + AccessResult CheckDestructorAccess(SourceLocation Loc, + const RecordType *Record); + AccessResult CheckMemberOperatorAccess(SourceLocation Loc, + Expr *ObjectExpr, + NamedDecl *D, + AccessSpecifier Access); + AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, + bool IsBaseToDerived, + QualType Base, QualType Derived, + const CXXBasePath &Path, + bool ForceCheck = false, + bool ForceUnprivileged = false, + AccessDiagnosticsKind ADK = ADK_normal); + + void CheckLookupAccess(const LookupResult &R); + + void HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx); enum AbstractDiagSelID { AbstractNone = -1, @@ -2758,17 +2906,28 @@ public: /// TemplateArgumentList *Deduced; + /// \brief The source location at which template argument + /// deduction is occurring. + SourceLocation Loc; + // do not implement these TemplateDeductionInfo(const TemplateDeductionInfo&); TemplateDeductionInfo &operator=(const TemplateDeductionInfo&); public: - TemplateDeductionInfo(ASTContext &Context) : Context(Context), Deduced(0) { } + TemplateDeductionInfo(ASTContext &Context, SourceLocation Loc) + : Context(Context), Deduced(0), Loc(Loc) { } ~TemplateDeductionInfo() { // FIXME: if (Deduced) Deduced->Destroy(Context); } + /// \brief Returns the location at which template argument is + /// occuring. + SourceLocation getLocation() const { + return Loc; + } + /// \brief Take ownership of the deduced template argument list. TemplateArgumentList *take() { TemplateArgumentList *Result = Deduced; @@ -2866,20 +3025,21 @@ public: FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, + SourceLocation Loc, TemplatePartialOrderingContext TPOC); - FunctionDecl *getMostSpecialized(FunctionDecl **Specializations, - unsigned NumSpecializations, - TemplatePartialOrderingContext TPOC, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - unsigned *Index = 0); + UnresolvedSetIterator getMostSpecialized(UnresolvedSetIterator SBegin, + UnresolvedSetIterator SEnd, + TemplatePartialOrderingContext TPOC, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag); ClassTemplatePartialSpecializationDecl * getMoreSpecializedPartialSpecialization( ClassTemplatePartialSpecializationDecl *PS1, - ClassTemplatePartialSpecializationDecl *PS2); + ClassTemplatePartialSpecializationDecl *PS2, + SourceLocation Loc); void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, @@ -2893,7 +3053,8 @@ public: // MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D, - const TemplateArgumentList *Innermost = 0); + const TemplateArgumentList *Innermost = 0, + bool RelativeToPrimary = false); /// \brief A template instantiation that is currently in progress. struct ActiveTemplateInstantiation { @@ -3243,6 +3404,9 @@ public: /// variables. LocalInstantiationScope *CurrentInstantiationScope; + /// \brief The number of typos corrected by CorrectTypo. + unsigned TyposCorrected; + /// \brief An entity for which implicit template instantiation is required. /// /// The source location associated with the declaration is the first place in @@ -3550,6 +3714,11 @@ public: // to their respective pointers (C99 6.3.2.1). void DefaultFunctionArrayConversion(Expr *&expr); + // DefaultFunctionArrayLvalueConversion - converts functions and + // arrays to their respective pointers and performs the + // lvalue-to-rvalue conversion. + void DefaultFunctionArrayLvalueConversion(Expr *&expr); + // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that // do not have a prototype. Integer promotions are performed on each // argument, and arguments that have type float are promoted to double. @@ -3944,12 +4113,15 @@ public: //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system + +public: + SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, + unsigned ByteNo) const; + private: bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); - SourceLocation getLocationOfStringLiteralByte(const StringLiteral *SL, - unsigned ByteNo) const; bool CheckablePrintfAttr(const FormatAttr *Format, CallExpr *TheCall); bool CheckObjCString(Expr *Arg); @@ -3957,7 +4129,7 @@ private: CallExpr *TheCall); bool SemaBuiltinVAStart(CallExpr *TheCall); bool SemaBuiltinUnorderedCompare(CallExpr *TheCall); - bool SemaBuiltinUnaryFP(CallExpr *TheCall); + bool SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg=1); bool SemaBuiltinStackAddress(CallExpr *TheCall); public: @@ -3987,7 +4159,6 @@ private: const PartialDiagnostic &PD, bool Equality = false); void CheckImplicitConversion(Expr *E, QualType Target); - }; //===--------------------------------------------------------------------===// diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 51f9e30..eca8bb4 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -16,6 +16,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/ExprCXX.h" + using namespace clang; /// SetMemberAccessSpecifier - Set the access specifier of a member. @@ -47,192 +49,500 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl, return false; } -/// Find a class on the derivation path between Derived and Base that is -/// inaccessible. If @p NoPrivileges is true, special access rights (members -/// and friends) are not considered. -const CXXBaseSpecifier *Sema::FindInaccessibleBase( - QualType Derived, QualType Base, CXXBasePaths &Paths, bool NoPrivileges) { - Base = Context.getCanonicalType(Base).getUnqualifiedType(); - assert(!Paths.isAmbiguous(Base) && - "Can't check base class access if set of paths is ambiguous"); - assert(Paths.isRecordingPaths() && - "Can't check base class access without recorded paths"); - - - const CXXBaseSpecifier *InaccessibleBase = 0; - - const CXXRecordDecl *CurrentClassDecl = 0; - if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(getCurFunctionDecl())) - CurrentClassDecl = MD->getParent(); - - for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathsEnd = Paths.end(); - Path != PathsEnd; ++Path) { - - bool FoundInaccessibleBase = false; - - for (CXXBasePath::const_iterator Element = Path->begin(), - ElementEnd = Path->end(); Element != ElementEnd; ++Element) { - const CXXBaseSpecifier *Base = Element->Base; - - switch (Base->getAccessSpecifier()) { - default: - assert(0 && "invalid access specifier"); - case AS_public: - // Nothing to do. - break; - case AS_private: - // FIXME: Check if the current function/class is a friend. - if (NoPrivileges || CurrentClassDecl != Element->Class) - FoundInaccessibleBase = true; - break; - case AS_protected: - // FIXME: Implement - break; - } +namespace { +struct EffectiveContext { + EffectiveContext() : Record(0), Function(0) {} + + explicit EffectiveContext(DeclContext *DC) { + if (isa<FunctionDecl>(DC)) { + Function = cast<FunctionDecl>(DC); + DC = Function->getDeclContext(); + } else + Function = 0; + + if (isa<CXXRecordDecl>(DC)) + Record = cast<CXXRecordDecl>(DC)->getCanonicalDecl(); + else + Record = 0; + } + + bool isClass(const CXXRecordDecl *R) const { + return R->getCanonicalDecl() == Record; + } + + CXXRecordDecl *Record; + FunctionDecl *Function; +}; +} + +static CXXRecordDecl *FindDeclaringClass(NamedDecl *D) { + CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext()); + while (DeclaringClass->isAnonymousStructOrUnion()) + DeclaringClass = cast<CXXRecordDecl>(DeclaringClass->getDeclContext()); + return DeclaringClass; +} + +static Sema::AccessResult GetFriendKind(Sema &S, + const EffectiveContext &EC, + const CXXRecordDecl *Class) { + if (EC.isClass(Class)) + return Sema::AR_accessible; + + // FIXME: implement + return Sema::AR_inaccessible; +} - if (FoundInaccessibleBase) { - InaccessibleBase = Base; - break; +/// Finds the best path from the naming class to the declaring class, +/// taking friend declarations into account. +/// +/// \return null if friendship is dependent +static CXXBasePath *FindBestPath(Sema &S, + const EffectiveContext &EC, + CXXRecordDecl *Derived, + CXXRecordDecl *Base, + CXXBasePaths &Paths) { + // Derive the paths to the desired base. + bool isDerived = Derived->isDerivedFrom(Base, Paths); + assert(isDerived && "derived class not actually derived from base"); + (void) isDerived; + + CXXBasePath *BestPath = 0; + + // Derive the friend-modified access along each path. + for (CXXBasePaths::paths_iterator PI = Paths.begin(), PE = Paths.end(); + PI != PE; ++PI) { + + // Walk through the path backwards. + AccessSpecifier PathAccess = AS_public; + CXXBasePath::iterator I = PI->end(), E = PI->begin(); + while (I != E) { + --I; + + AccessSpecifier BaseAccess = I->Base->getAccessSpecifier(); + if (BaseAccess != AS_public) { + switch (GetFriendKind(S, EC, I->Class)) { + case Sema::AR_inaccessible: break; + case Sema::AR_accessible: BaseAccess = AS_public; break; + case Sema::AR_dependent: return 0; + case Sema::AR_delayed: + llvm_unreachable("friend resolution is never delayed"); break; + } } + + PathAccess = CXXRecordDecl::MergeAccess(BaseAccess, PathAccess); } - if (!FoundInaccessibleBase) { - // We found a path to the base, our work here is done. - return 0; + // Note that we modify the path's Access field to the + // friend-modified access. + if (BestPath == 0 || PathAccess < BestPath->Access) { + BestPath = &*PI; + BestPath->Access = PathAccess; } } - assert(InaccessibleBase && "no path found, but no inaccessible base"); - return InaccessibleBase; + return BestPath; } -/// CheckBaseClassAccess - Check that a derived class can access its base class -/// and report an error if it can't. [class.access.base] -bool Sema::CheckBaseClassAccess(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, - CXXBasePaths &Paths, SourceLocation AccessLoc, - DeclarationName Name) { +/// Diagnose the path which caused the given declaration or base class +/// to become inaccessible. +static void DiagnoseAccessPath(Sema &S, + const EffectiveContext &EC, + CXXRecordDecl *NamingClass, + CXXRecordDecl *DeclaringClass, + NamedDecl *D, AccessSpecifier Access) { + // Easy case: the decl's natural access determined its path access. + // We have to check against AS_private here in case Access is AS_none, + // indicating a non-public member of a private base class. + // + // DependentFriend should be impossible here. + if (D && (Access == D->getAccess() || D->getAccess() == AS_private)) { + switch (GetFriendKind(S, EC, DeclaringClass)) { + case Sema::AR_inaccessible: { + S.Diag(D->getLocation(), diag::note_access_natural) + << (unsigned) (Access == AS_protected) + << /*FIXME: not implicitly*/ 0; + return; + } - if (!getLangOptions().AccessControl) - return false; - const CXXBaseSpecifier *InaccessibleBase = FindInaccessibleBase( - Derived, Base, Paths); + case Sema::AR_accessible: break; - if (InaccessibleBase) { - Diag(AccessLoc, InaccessibleBaseID) - << Derived << Base << Name; + case Sema::AR_dependent: + case Sema::AR_delayed: + llvm_unreachable("dependent/delayed not allowed"); + return; + } + } - AccessSpecifier AS = InaccessibleBase->getAccessSpecifierAsWritten(); + CXXBasePaths Paths; + CXXBasePath &Path = *FindBestPath(S, EC, NamingClass, DeclaringClass, Paths); - // If there's no written access specifier, then the inheritance specifier - // is implicitly private. - if (AS == AS_none) - Diag(InaccessibleBase->getSourceRange().getBegin(), - diag::note_inheritance_implicitly_private_here); - else - Diag(InaccessibleBase->getSourceRange().getBegin(), - diag::note_inheritance_specifier_here) << AS; + CXXBasePath::iterator I = Path.end(), E = Path.begin(); + while (I != E) { + --I; - return true; + const CXXBaseSpecifier *BS = I->Base; + AccessSpecifier BaseAccess = BS->getAccessSpecifier(); + + // If this is public inheritance, or the derived class is a friend, + // skip this step. + if (BaseAccess == AS_public) + continue; + + switch (GetFriendKind(S, EC, I->Class)) { + case Sema::AR_accessible: continue; + case Sema::AR_inaccessible: break; + + case Sema::AR_dependent: + case Sema::AR_delayed: + llvm_unreachable("dependent friendship, should not be diagnosing"); + } + + // Check whether this base specifier is the tighest point + // constraining access. We have to check against AS_private for + // the same reasons as above. + if (BaseAccess == AS_private || BaseAccess >= Access) { + + // We're constrained by inheritance, but we want to say + // "declared private here" if we're diagnosing a hierarchy + // conversion and this is the final step. + unsigned diagnostic; + if (D) diagnostic = diag::note_access_constrained_by_path; + else if (I + 1 == Path.end()) diagnostic = diag::note_access_natural; + else diagnostic = diag::note_access_constrained_by_path; + + S.Diag(BS->getSourceRange().getBegin(), diagnostic) + << BS->getSourceRange() + << (BaseAccess == AS_protected) + << (BS->getAccessSpecifierAsWritten() == AS_none); + return; + } } - return false; + llvm_unreachable("access not apparently constrained by path"); } -/// Diagnose the path which caused the given declaration to become -/// inaccessible. -static void DiagnoseAccessPath(Sema &S, const LookupResult &R, NamedDecl *D, - AccessSpecifier Access) { - // Easy case: the decl's natural access determined its path access. - if (Access == D->getAccess() || D->getAccess() == AS_private) { - S.Diag(D->getLocation(), diag::note_access_natural) - << (unsigned) (Access == AS_protected); - return; +/// Diagnose an inaccessible class member. +static void DiagnoseInaccessibleMember(Sema &S, SourceLocation Loc, + const EffectiveContext &EC, + CXXRecordDecl *NamingClass, + AccessSpecifier Access, + const Sema::AccessedEntity &Entity) { + NamedDecl *D = Entity.getTargetDecl(); + CXXRecordDecl *DeclaringClass = FindDeclaringClass(D); + + if (isa<CXXConstructorDecl>(D)) { + unsigned DiagID = (Access == AS_protected ? diag::err_access_ctor_protected + : diag::err_access_ctor_private); + S.Diag(Loc, DiagID) + << S.Context.getTypeDeclType(DeclaringClass); + } else { + unsigned DiagID = (Access == AS_protected ? diag::err_access_protected + : diag::err_access_private); + S.Diag(Loc, DiagID) + << D->getDeclName() + << S.Context.getTypeDeclType(DeclaringClass); } + DiagnoseAccessPath(S, EC, NamingClass, DeclaringClass, D, Access); +} - // TODO: flesh this out - S.Diag(D->getLocation(), diag::note_access_constrained_by_path) - << (unsigned) (Access == AS_protected); +/// Diagnose an inaccessible hierarchy conversion. +static void DiagnoseInaccessibleBase(Sema &S, SourceLocation Loc, + const EffectiveContext &EC, + AccessSpecifier Access, + const Sema::AccessedEntity &Entity, + Sema::AccessDiagnosticsKind ADK) { + if (ADK == Sema::ADK_covariance) { + S.Diag(Loc, diag::err_covariant_return_inaccessible_base) + << S.Context.getTypeDeclType(Entity.getDerivedClass()) + << S.Context.getTypeDeclType(Entity.getBaseClass()) + << (Access == AS_protected); + } else if (Entity.getKind() == Sema::AccessedEntity::BaseToDerivedConversion) { + S.Diag(Loc, diag::err_downcast_from_inaccessible_base) + << S.Context.getTypeDeclType(Entity.getDerivedClass()) + << S.Context.getTypeDeclType(Entity.getBaseClass()) + << (Access == AS_protected); + } else { + S.Diag(Loc, diag::err_upcast_to_inaccessible_base) + << S.Context.getTypeDeclType(Entity.getDerivedClass()) + << S.Context.getTypeDeclType(Entity.getBaseClass()) + << (Access == AS_protected); + } + DiagnoseAccessPath(S, EC, Entity.getDerivedClass(), + Entity.getBaseClass(), 0, Access); } -/// Checks access to the given declaration in the current context. -/// -/// \param R the means via which the access was made; must have a naming -/// class set -/// \param D the declaration accessed -/// \param Access the best access along any inheritance path from the -/// naming class to the declaration. AS_none means the path is impossible -bool Sema::CheckAccess(const LookupResult &R, NamedDecl *D, - AccessSpecifier Access) { - assert(R.getNamingClass() && "performing access check without naming class"); +static void DiagnoseBadAccess(Sema &S, + SourceLocation Loc, + const EffectiveContext &EC, + CXXRecordDecl *NamingClass, + AccessSpecifier Access, + const Sema::AccessedEntity &Entity, + Sema::AccessDiagnosticsKind ADK) { + if (Entity.isMemberAccess()) + DiagnoseInaccessibleMember(S, Loc, EC, NamingClass, Access, Entity); + else + DiagnoseInaccessibleBase(S, Loc, EC, Access, Entity, ADK); +} - // If the access path is public, it's accessible everywhere. - if (Access == AS_public) - return false; - // Otherwise, derive the current class context. - DeclContext *DC = CurContext; - while (isa<CXXRecordDecl>(DC) && - cast<CXXRecordDecl>(DC)->isAnonymousStructOrUnion()) - DC = DC->getParent(); - - CXXRecordDecl *CurRecord; - if (isa<CXXRecordDecl>(DC)) - CurRecord = cast<CXXRecordDecl>(DC); - else if (isa<CXXMethodDecl>(DC)) - CurRecord = cast<CXXMethodDecl>(DC)->getParent(); - else { - Diag(R.getNameLoc(), diag::err_access_outside_class) - << (Access == AS_protected); - DiagnoseAccessPath(*this, R, D, Access); - return true; +/// Try to elevate access using friend declarations. This is +/// potentially quite expensive. +static void TryElevateAccess(Sema &S, + const EffectiveContext &EC, + const Sema::AccessedEntity &Entity, + AccessSpecifier &Access) { + CXXRecordDecl *DeclaringClass; + if (Entity.isMemberAccess()) { + DeclaringClass = FindDeclaringClass(Entity.getTargetDecl()); + } else { + DeclaringClass = Entity.getBaseClass(); } + CXXRecordDecl *NamingClass = Entity.getNamingClass(); + + // Adjust the declaration of the referred entity. + AccessSpecifier DeclAccess = AS_none; + if (Entity.isMemberAccess()) { + NamedDecl *Target = Entity.getTargetDecl(); + + DeclAccess = Target->getAccess(); + if (DeclAccess != AS_public) { + switch (GetFriendKind(S, EC, DeclaringClass)) { + case Sema::AR_accessible: DeclAccess = AS_public; break; + case Sema::AR_inaccessible: break; + case Sema::AR_dependent: /* FIXME: delay dependent friendship */ return; + case Sema::AR_delayed: llvm_unreachable("friend status is never delayed"); + } + } + + if (DeclaringClass == NamingClass) { + Access = DeclAccess; + return; + } + } + + assert(DeclaringClass != NamingClass); - CXXRecordDecl *NamingClass = R.getNamingClass(); + // Append the declaration's access if applicable. + CXXBasePaths Paths; + CXXBasePath *Path = FindBestPath(S, EC, Entity.getNamingClass(), + DeclaringClass, Paths); + if (!Path) { + // FIXME: delay dependent friendship + return; + } + + // Grab the access along the best path. + AccessSpecifier NewAccess = Path->Access; + if (Entity.isMemberAccess()) + NewAccess = CXXRecordDecl::MergeAccess(NewAccess, DeclAccess); + + assert(NewAccess <= Access && "access along best path worse than direct?"); + Access = NewAccess; +} + +/// Checks access to an entity from the given effective context. +static Sema::AccessResult CheckEffectiveAccess(Sema &S, + const EffectiveContext &EC, + SourceLocation Loc, + Sema::AccessedEntity const &Entity, + Sema::AccessDiagnosticsKind ADK) { + AccessSpecifier Access = Entity.getAccess(); + assert(Access != AS_public); + + CXXRecordDecl *NamingClass = Entity.getNamingClass(); while (NamingClass->isAnonymousStructOrUnion()) // This should be guaranteed by the fact that the decl has // non-public access. If not, we should make it guaranteed! NamingClass = cast<CXXRecordDecl>(NamingClass); + if (!EC.Record) { + TryElevateAccess(S, EC, Entity, Access); + if (Access == AS_public) return Sema::AR_accessible; + + if (ADK != Sema::ADK_quiet) + DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK); + return Sema::AR_inaccessible; + } + // White-list accesses from within the declaring class. - if (Access != AS_none && - CurRecord->getCanonicalDecl() == NamingClass->getCanonicalDecl()) - return false; + if (Access != AS_none && EC.isClass(NamingClass)) + return Sema::AR_accessible; + + // If the access is worse than 'protected', try to promote to it using + // friend declarations. + bool TriedElevation = false; + if (Access != AS_protected) { + TryElevateAccess(S, EC, Entity, Access); + if (Access == AS_public) return Sema::AR_accessible; + TriedElevation = true; + } // Protected access. if (Access == AS_protected) { // FIXME: implement [class.protected]p1 - if (CurRecord->isDerivedFrom(NamingClass)) - return false; + if (EC.Record->isDerivedFrom(NamingClass)) + return Sema::AR_accessible; - // FIXME: dependent classes + // FIXME: delay dependent classes } - // FIXME: friends + // We're about to reject; one last chance to promote access. + if (!TriedElevation) { + TryElevateAccess(S, EC, Entity, Access); + if (Access == AS_public) return Sema::AR_accessible; + } + + // Okay, that's it, reject it. + if (ADK != Sema::ADK_quiet) + DiagnoseBadAccess(S, Loc, EC, NamingClass, Access, Entity, ADK); + return Sema::AR_inaccessible; +} - // Okay, it's a bad access, reject it. +static Sema::AccessResult CheckAccess(Sema &S, SourceLocation Loc, + const Sema::AccessedEntity &Entity, + Sema::AccessDiagnosticsKind ADK + = Sema::ADK_normal) { + // If the access path is public, it's accessible everywhere. + if (Entity.getAccess() == AS_public) + 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 + // access control. + if (S.CurContext->isFileContext() && S.ParsingDeclDepth) { + assert(ADK == Sema::ADK_normal && "delaying abnormal access check"); + S.DelayedDiagnostics.push_back( + Sema::DelayedDiagnostic::makeAccess(Loc, Entity)); + return Sema::AR_delayed; + } - - CXXRecordDecl *DeclaringClass = cast<CXXRecordDecl>(D->getDeclContext()); + return CheckEffectiveAccess(S, EffectiveContext(S.CurContext), + Loc, Entity, ADK); +} - if (Access == AS_protected) { - Diag(R.getNameLoc(), diag::err_access_protected) - << Context.getTypeDeclType(DeclaringClass) - << Context.getTypeDeclType(CurRecord); - DiagnoseAccessPath(*this, R, D, Access); - return true; - } +void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *Ctx) { + // Pretend we did this from the context of the newly-parsed + // declaration. + EffectiveContext EC(Ctx->getDeclContext()); + + if (CheckEffectiveAccess(*this, EC, DD.Loc, DD.AccessData, ADK_normal)) + DD.Triggered = true; +} + +Sema::AccessResult Sema::CheckUnresolvedLookupAccess(UnresolvedLookupExpr *E, + NamedDecl *D, + AccessSpecifier Access) { + if (!getLangOptions().AccessControl || !E->getNamingClass()) + return AR_accessible; - assert(Access == AS_private || Access == AS_none); - Diag(R.getNameLoc(), diag::err_access_private) - << Context.getTypeDeclType(DeclaringClass) - << Context.getTypeDeclType(CurRecord); - DiagnoseAccessPath(*this, R, D, Access); - return true; + return CheckAccess(*this, E->getNameLoc(), + AccessedEntity::makeMember(E->getNamingClass(), Access, D)); +} + +/// Perform access-control checking on a previously-unresolved member +/// access which has now been resolved to a member. +Sema::AccessResult Sema::CheckUnresolvedMemberAccess(UnresolvedMemberExpr *E, + NamedDecl *D, + AccessSpecifier Access) { + if (!getLangOptions().AccessControl) + return AR_accessible; + + return CheckAccess(*this, E->getMemberLoc(), + AccessedEntity::makeMember(E->getNamingClass(), Access, D)); +} + +Sema::AccessResult Sema::CheckDestructorAccess(SourceLocation Loc, + const RecordType *RT) { + if (!getLangOptions().AccessControl) + return AR_accessible; + + CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); + CXXDestructorDecl *Dtor = NamingClass->getDestructor(Context); + + AccessSpecifier Access = Dtor->getAccess(); + if (Access == AS_public) + return AR_accessible; + + return CheckAccess(*this, Loc, + AccessedEntity::makeMember(NamingClass, Access, Dtor)); +} + +/// Checks access to a constructor. +Sema::AccessResult Sema::CheckConstructorAccess(SourceLocation UseLoc, + CXXConstructorDecl *Constructor, + AccessSpecifier Access) { + if (!getLangOptions().AccessControl) + return AR_accessible; + + CXXRecordDecl *NamingClass = Constructor->getParent(); + return CheckAccess(*this, UseLoc, + AccessedEntity::makeMember(NamingClass, Access, Constructor)); +} + +/// Checks access to an overloaded member operator, including +/// conversion operators. +Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, + Expr *ObjectExpr, + NamedDecl *MemberOperator, + AccessSpecifier Access) { + if (!getLangOptions().AccessControl) + return AR_accessible; + + const RecordType *RT = ObjectExpr->getType()->getAs<RecordType>(); + assert(RT && "found member operator but object expr not of record type"); + CXXRecordDecl *NamingClass = cast<CXXRecordDecl>(RT->getDecl()); + + return CheckAccess(*this, OpLoc, + AccessedEntity::makeMember(NamingClass, Access, MemberOperator)); +} + +/// Checks access for a hierarchy conversion. +/// +/// \param IsBaseToDerived whether this is a base-to-derived conversion (true) +/// or a derived-to-base conversion (false) +/// \param ForceCheck true if this check should be performed even if access +/// control is disabled; some things rely on this for semantics +/// \param ForceUnprivileged true if this check should proceed as if the +/// context had no special privileges +/// \param ADK controls the kind of diagnostics that are used +Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, + bool IsBaseToDerived, + QualType Base, + QualType Derived, + const CXXBasePath &Path, + bool ForceCheck, + bool ForceUnprivileged, + AccessDiagnosticsKind ADK) { + if (!ForceCheck && !getLangOptions().AccessControl) + return AR_accessible; + + if (Path.Access == AS_public) + return AR_accessible; + + // TODO: preserve the information about which types exactly were used. + CXXRecordDecl *BaseD, *DerivedD; + BaseD = cast<CXXRecordDecl>(Base->getAs<RecordType>()->getDecl()); + DerivedD = cast<CXXRecordDecl>(Derived->getAs<RecordType>()->getDecl()); + AccessedEntity Entity = AccessedEntity::makeBaseClass(IsBaseToDerived, + BaseD, DerivedD, + Path.Access); + + if (ForceUnprivileged) + return CheckEffectiveAccess(*this, EffectiveContext(), + AccessLoc, Entity, ADK); + return CheckAccess(*this, AccessLoc, Entity, ADK); } /// Checks access to all the declarations in the given result set. -void Sema::CheckAccess(const LookupResult &R) { +void Sema::CheckLookupAccess(const LookupResult &R) { + assert(getLangOptions().AccessControl + && "performing access check without access control"); + assert(R.getNamingClass() && "performing access check without naming class"); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - CheckAccess(R, *I, I.getAccess()); + if (I.getAccess() != AS_public) + CheckAccess(*this, R.getNameLoc(), + AccessedEntity::makeMember(R.getNamingClass(), + I.getAccess(), *I)); } diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 57c4f9b..0097cd3 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -204,7 +204,30 @@ bool UnwrapDissimilarPointerTypes(QualType& T1, QualType& T2) { T2 = T2PtrType->getPointeeType(); return true; } - + const ObjCObjectPointerType *T1ObjCPtrType = + T1->getAs<ObjCObjectPointerType>(), + *T2ObjCPtrType = + T2->getAs<ObjCObjectPointerType>(); + if (T1ObjCPtrType) { + if (T2ObjCPtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2ObjCPtrType->getPointeeType(); + return true; + } + else if (T2PtrType) { + T1 = T1ObjCPtrType->getPointeeType(); + T2 = T2PtrType->getPointeeType(); + return true; + } + } + else if (T2ObjCPtrType) { + if (T1PtrType) { + T2 = T2ObjCPtrType->getPointeeType(); + T1 = T1PtrType->getPointeeType(); + return true; + } + } + const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), *T2MPType = T2->getAs<MemberPointerType>(); if (T1MPType && T2MPType) { @@ -225,9 +248,9 @@ 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->isPointerType() || SrcType->isMemberPointerType()) && + assert((SrcType->isAnyPointerType() || SrcType->isMemberPointerType()) && "Source type is not pointer or pointer to member."); - assert((DestType->isPointerType() || DestType->isMemberPointerType()) && + assert((DestType->isAnyPointerType() || DestType->isMemberPointerType()) && "Destination type is not pointer or pointer to member."); QualType UnwrappedSrcType = Self.Context.getCanonicalType(SrcType), @@ -368,7 +391,7 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType, } // C++ 5.2.7p6: Otherwise, v shall be [polymorphic]. - const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(Self.Context); + const RecordDecl *SrcDecl = SrcRecord->getDecl()->getDefinition(); assert(SrcDecl && "Definition missing"); if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) { Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic) @@ -388,7 +411,7 @@ void CheckConstCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange) { if (!DestType->isLValueReferenceType()) - Self.DefaultFunctionArrayConversion(SrcExpr); + Self.DefaultFunctionArrayLvalueConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success @@ -407,7 +430,7 @@ CheckReinterpretCast(Sema &Self, Expr *&SrcExpr, QualType DestType, const SourceRange &OpRange, const SourceRange &DestRange, CastExpr::CastKind &Kind) { if (!DestType->isLValueReferenceType()) - Self.DefaultFunctionArrayConversion(SrcExpr); + Self.DefaultFunctionArrayLvalueConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, @@ -434,7 +457,7 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType, } if (!DestType->isLValueReferenceType() && !DestType->isRecordType()) - Self.DefaultFunctionArrayConversion(SrcExpr); + Self.DefaultFunctionArrayLvalueConversion(SrcExpr); unsigned msg = diag::err_bad_cxx_cast_generic; if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg, @@ -755,9 +778,10 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType, return TC_Failed; } - if (!CStyle && Self.CheckBaseClassAccess(DestType, SrcType, - diag::err_downcast_from_inaccessible_base, Paths, - OpRange.getBegin(), DeclarationName())) { + if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(), + /*IsBaseToDerived*/ true, + SrcType, DestType, + Paths.front())) { msg = 0; return TC_Failed; } @@ -821,9 +845,10 @@ TryStaticMemberPointerUpcast(Sema &Self, QualType SrcType, QualType DestType, return TC_Failed; } - if (!CStyle && Self.CheckBaseClassAccess(DestType, SrcType, - diag::err_downcast_from_inaccessible_base, Paths, - OpRange.getBegin(), DeclarationName())) { + if (!CStyle && Self.CheckBaseClassAccess(OpRange.getBegin(), + /*IsBaseToDerived*/ false, + DestType, SrcType, + Paths.front())) { msg = 0; return TC_Failed; } @@ -1083,10 +1108,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, return TC_Failed; } - bool destIsPtr = - CStyle? DestType->isAnyPointerType() : DestType->isPointerType(); - bool srcIsPtr = - CStyle ? SrcType->isAnyPointerType() : SrcType->isPointerType(); + bool destIsPtr = DestType->isAnyPointerType(); + bool srcIsPtr = SrcType->isAnyPointerType(); 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. @@ -1197,7 +1220,7 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr, return false; if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType()) - DefaultFunctionArrayConversion(CastExpr); + DefaultFunctionArrayLvalueConversion(CastExpr); // C++ [expr.cast]p5: The conversions performed by // - a const_cast, diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 7a0b625..52e9e9b 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -241,6 +241,10 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) { DeclContext *DC = computeDeclContext(SS, true); if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) { + // If this is a dependent type, then we consider it complete. + if (Tag->isDependentContext()) + return false; + // If we're currently defining this type, then lookup into the // type is okay: don't complain that it isn't complete yet. const TagType *TagT = Context.getTypeDeclType(Tag)->getAs<TagType>(); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6ff8b1d..b62cd19 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -14,7 +14,8 @@ #include "Sema.h" #include "clang/Analysis/CFG.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/Analyses/PrintfFormatString.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" @@ -140,12 +141,16 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (SemaBuiltinUnorderedCompare(TheCall)) return ExprError(); break; + case Builtin::BI__builtin_fpclassify: + if (SemaBuiltinFPClassification(TheCall, 6)) + return ExprError(); + break; case Builtin::BI__builtin_isfinite: case Builtin::BI__builtin_isinf: case Builtin::BI__builtin_isinf_sign: case Builtin::BI__builtin_isnan: case Builtin::BI__builtin_isnormal: - if (SemaBuiltinUnaryFP(TheCall)) + if (SemaBuiltinFPClassification(TheCall)) return ExprError(); break; case Builtin::BI__builtin_return_address: @@ -583,20 +588,21 @@ bool Sema::SemaBuiltinUnorderedCompare(CallExpr *TheCall) { return false; } -/// SemaBuiltinUnorderedCompare - Handle functions like __builtin_isnan and -/// friends. This is declared to take (...), so we have to check everything. -bool Sema::SemaBuiltinUnaryFP(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 1) +/// SemaBuiltinSemaBuiltinFPClassification - Handle functions like +/// __builtin_isnan and friends. This is declared to take (...), so we have +/// to check everything. +bool Sema::SemaBuiltinFPClassification(CallExpr *TheCall, unsigned LastArg) { + if (TheCall->getNumArgs() < LastArg) return Diag(TheCall->getLocEnd(), diag::err_typecheck_call_too_few_args) << 0 /*function call*/; - if (TheCall->getNumArgs() > 1) - return Diag(TheCall->getArg(1)->getLocStart(), + if (TheCall->getNumArgs() > LastArg) + return Diag(TheCall->getArg(LastArg)->getLocStart(), diag::err_typecheck_call_too_many_args) << 0 /*function call*/ - << SourceRange(TheCall->getArg(1)->getLocStart(), + << SourceRange(TheCall->getArg(LastArg)->getLocStart(), (*(TheCall->arg_end()-1))->getLocEnd()); - Expr *OrigArg = TheCall->getArg(0); + Expr *OrigArg = TheCall->getArg(LastArg-1); if (OrigArg->isTypeDependent()) return false; @@ -748,7 +754,7 @@ bool Sema::SemaBuiltinEHReturnDataRegNo(CallExpr *TheCall) { if (!TheCall->getArg(0)->isIntegerConstantExpr(Result, Context)) return Diag(TheCall->getLocStart(), diag::err_expr_not_ice) << TheCall->getArg(0)->getSourceRange(); - + return false; } @@ -845,8 +851,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, } if (isConstant) { - const VarDecl *Def = 0; - if (const Expr *Init = VD->getDefinition(Def)) + if (const Expr *Init = VD->getAnyInitializer()) return SemaCheckStringLiteral(Init, TheCall, HasVAListArg, format_idx, firstDataArg); } @@ -925,7 +930,7 @@ Sema::CheckNonNullArguments(const NonNullAttr *NonNull, for (NonNullAttr::iterator i = NonNull->begin(), e = NonNull->end(); i != e; ++i) { const Expr *ArgExpr = TheCall->getArg(*i); - if (ArgExpr->isNullPointerConstant(Context, + if (ArgExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNotNull)) Diag(TheCall->getCallee()->getLocStart(), diag::warn_null_arg) << ArgExpr->getSourceRange(); @@ -1032,248 +1037,309 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, << OrigFormatExpr->getSourceRange(); } -void Sema::CheckPrintfString(const StringLiteral *FExpr, - const Expr *OrigFormatExpr, - const CallExpr *TheCall, bool HasVAListArg, - unsigned format_idx, unsigned firstDataArg) { - - const ObjCStringLiteral *ObjCFExpr = - dyn_cast<ObjCStringLiteral>(OrigFormatExpr); - - // CHECK: is the format string a wide literal? - if (FExpr->isWide()) { - Diag(FExpr->getLocStart(), - diag::warn_printf_format_string_is_wide_literal) - << OrigFormatExpr->getSourceRange(); - return; - } +namespace { +class CheckPrintfHandler : public analyze_printf::FormatStringHandler { + Sema &S; + const StringLiteral *FExpr; + const Expr *OrigFormatExpr; + unsigned NumConversions; + const unsigned NumDataArgs; + const bool IsObjCLiteral; + const char *Beg; // Start of format string. + const bool HasVAListArg; + const CallExpr *TheCall; + unsigned FormatIdx; +public: + CheckPrintfHandler(Sema &s, const StringLiteral *fexpr, + const Expr *origFormatExpr, + unsigned numDataArgs, bool isObjCLiteral, + const char *beg, bool hasVAListArg, + const CallExpr *theCall, unsigned formatIdx) + : S(s), FExpr(fexpr), OrigFormatExpr(origFormatExpr), + NumConversions(0), NumDataArgs(numDataArgs), + IsObjCLiteral(isObjCLiteral), Beg(beg), + HasVAListArg(hasVAListArg), + TheCall(theCall), FormatIdx(formatIdx) {} + + void DoneProcessing(); + + void HandleIncompleteFormatSpecifier(const char *startSpecifier, + unsigned specifierLen); + + void + HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); + + void HandleNullChar(const char *nullCharacter); + + bool HandleFormatSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen); +private: + SourceRange getFormatStringRange(); + SourceRange getFormatSpecifierRange(const char *startSpecifier, + unsigned specifierLen); + SourceLocation getLocationOfByte(const char *x); + + bool HandleAmount(const analyze_printf::OptionalAmount &Amt, + unsigned MissingArgDiag, unsigned BadTypeDiag, + const char *startSpecifier, unsigned specifierLen); + void HandleFlags(const analyze_printf::FormatSpecifier &FS, + llvm::StringRef flag, llvm::StringRef cspec, + const char *startSpecifier, unsigned specifierLen); + + const Expr *getDataArg(unsigned i) const; +}; +} - // Str - The format string. NOTE: this is NOT null-terminated! - const char *Str = FExpr->getStrData(); +SourceRange CheckPrintfHandler::getFormatStringRange() { + return OrigFormatExpr->getSourceRange(); +} - // CHECK: empty format string? - unsigned StrLen = FExpr->getByteLength(); +SourceRange CheckPrintfHandler:: +getFormatSpecifierRange(const char *startSpecifier, unsigned specifierLen) { + return SourceRange(getLocationOfByte(startSpecifier), + getLocationOfByte(startSpecifier+specifierLen-1)); +} - if (StrLen == 0) { - Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string) - << OrigFormatExpr->getSourceRange(); - return; - } +SourceLocation CheckPrintfHandler::getLocationOfByte(const char *x) { + return S.getLocationOfStringLiteralByte(FExpr, x - Beg); +} - // We process the format string using a binary state machine. The - // current state is stored in CurrentState. - enum { - state_OrdChr, - state_Conversion - } CurrentState = state_OrdChr; +void CheckPrintfHandler:: +HandleIncompleteFormatSpecifier(const char *startSpecifier, + unsigned specifierLen) { + SourceLocation Loc = getLocationOfByte(startSpecifier); + S.Diag(Loc, diag::warn_printf_incomplete_specifier) + << getFormatSpecifierRange(startSpecifier, specifierLen); +} - // numConversions - The number of conversions seen so far. This is - // incremented as we traverse the format string. - unsigned numConversions = 0; +void CheckPrintfHandler:: +HandleInvalidConversionSpecifier(const analyze_printf::FormatSpecifier &FS, + const char *startSpecifier, + unsigned specifierLen) { + + ++NumConversions; + const analyze_printf::ConversionSpecifier &CS = + FS.getConversionSpecifier(); + SourceLocation Loc = getLocationOfByte(CS.getStart()); + S.Diag(Loc, diag::warn_printf_invalid_conversion) + << llvm::StringRef(CS.getStart(), CS.getLength()) + << getFormatSpecifierRange(startSpecifier, specifierLen); +} - // numDataArgs - The number of data arguments after the format - // string. This can only be determined for non vprintf-like - // functions. For those functions, this value is 1 (the sole - // va_arg argument). - unsigned numDataArgs = TheCall->getNumArgs()-firstDataArg; +void CheckPrintfHandler::HandleNullChar(const char *nullCharacter) { + // The presence of a null character is likely an error. + S.Diag(getLocationOfByte(nullCharacter), + diag::warn_printf_format_string_contains_null_char) + << getFormatStringRange(); +} - // Inspect the format string. - unsigned StrIdx = 0; +const Expr *CheckPrintfHandler::getDataArg(unsigned i) const { + return TheCall->getArg(FormatIdx + i); +} - // LastConversionIdx - Index within the format string where we last saw - // a '%' character that starts a new format conversion. - unsigned LastConversionIdx = 0; - for (; StrIdx < StrLen; ++StrIdx) { - // Is the number of detected conversion conversions greater than - // the number of matching data arguments? If so, stop. - if (!HasVAListArg && numConversions > numDataArgs) break; +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); +} - // Handle "\0" - if (Str[StrIdx] == '\0') { - // The string returned by getStrData() is not null-terminated, - // so the presence of a null character is likely an error. - Diag(getLocationOfStringLiteralByte(FExpr, StrIdx), - diag::warn_printf_format_string_contains_null_char) - << OrigFormatExpr->getSourceRange(); - return; - } +bool +CheckPrintfHandler::HandleAmount(const analyze_printf::OptionalAmount &Amt, + unsigned MissingArgDiag, + unsigned BadTypeDiag, + const char *startSpecifier, + unsigned specifierLen) { + + if (Amt.hasDataArgument()) { + ++NumConversions; + if (!HasVAListArg) { + if (NumConversions > NumDataArgs) { + S.Diag(getLocationOfByte(Amt.getStart()), MissingArgDiag) + << getFormatSpecifierRange(startSpecifier, specifierLen); + // Don't do any more checking. We will just emit + // spurious errors. + return false; + } - // Ordinary characters (not processing a format conversion). - if (CurrentState == state_OrdChr) { - if (Str[StrIdx] == '%') { - CurrentState = state_Conversion; - LastConversionIdx = StrIdx; + // Type check the data argument. It should be an 'int'. + // Although not in conformance with C99, we also allow the argument to be + // an 'unsigned int' as that is a reasonably safe case. GCC also + // doesn't emit a warning for that case. + const Expr *Arg = getDataArg(NumConversions); + QualType T = Arg->getType(); + + const analyze_printf::ArgTypeResult &ATR = Amt.getArgType(S.Context); + assert(ATR.isValid()); + + if (!ATR.matchesType(S.Context, T)) { + S.Diag(getLocationOfByte(Amt.getStart()), BadTypeDiag) + << ATR.getRepresentativeType(S.Context) << T + << getFormatSpecifierRange(startSpecifier, specifierLen) + << Arg->getSourceRange(); + // Don't do any more checking. We will just emit + // spurious errors. + return false; } - continue; } + } + return true; +} - // Seen '%'. Now processing a format conversion. - switch (Str[StrIdx]) { - // Handle dynamic precision or width specifier. - case '*': { - ++numConversions; - - if (!HasVAListArg) { - if (numConversions > numDataArgs) { - SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx); - - if (Str[StrIdx-1] == '.') - Diag(Loc, diag::warn_printf_asterisk_precision_missing_arg) - << OrigFormatExpr->getSourceRange(); - else - Diag(Loc, diag::warn_printf_asterisk_width_missing_arg) - << OrigFormatExpr->getSourceRange(); - - // Don't do any more checking. We'll just emit spurious errors. - return; - } +bool +CheckPrintfHandler::HandleFormatSpecifier(const analyze_printf::FormatSpecifier + &FS, + const char *startSpecifier, + unsigned specifierLen) { + + using namespace analyze_printf; + const ConversionSpecifier &CS = FS.getConversionSpecifier(); + + // First check if the field width, precision, and conversion specifier + // have matching data arguments. + if (!HandleAmount(FS.getFieldWidth(), + diag::warn_printf_asterisk_width_missing_arg, + diag::warn_printf_asterisk_width_wrong_type, + startSpecifier, specifierLen)) { + return false; + } - // Perform type checking on width/precision specifier. - const Expr *E = TheCall->getArg(format_idx+numConversions); - if (const BuiltinType *BT = E->getType()->getAs<BuiltinType>()) - if (BT->getKind() == BuiltinType::Int) - break; + if (!HandleAmount(FS.getPrecision(), + diag::warn_printf_asterisk_precision_missing_arg, + diag::warn_printf_asterisk_precision_wrong_type, + startSpecifier, specifierLen)) { + return false; + } - SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, StrIdx); + // Check for using an Objective-C specific conversion specifier + // in a non-ObjC literal. + if (!IsObjCLiteral && CS.isObjCArg()) { + HandleInvalidConversionSpecifier(FS, startSpecifier, specifierLen); - if (Str[StrIdx-1] == '.') - Diag(Loc, diag::warn_printf_asterisk_precision_wrong_type) - << E->getType() << E->getSourceRange(); - else - Diag(Loc, diag::warn_printf_asterisk_width_wrong_type) - << E->getType() << E->getSourceRange(); + // Continue checking the other format specifiers. + return true; + } - break; - } - } + if (!CS.consumesDataArgument()) { + // FIXME: Technically specifying a precision or field width here + // makes no sense. Worth issuing a warning at some point. + return true; + } - // Characters which can terminate a format conversion - // (e.g. "%d"). Characters that specify length modifiers or - // other flags are handled by the default case below. - // - // FIXME: additional checks will go into the following cases. - case 'i': - case 'd': - case 'o': - case 'u': - case 'x': - case 'X': - case 'D': - case 'O': - case 'U': - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - case 'a': - case 'A': - case 'c': - case 'C': - case 'S': - case 's': - case 'p': - ++numConversions; - CurrentState = state_OrdChr; - break; + ++NumConversions; - case 'm': - // FIXME: Warn in situations where this isn't supported! - CurrentState = state_OrdChr; - break; + // Are we using '%n'? Issue a warning about this being + // a possible security issue. + if (CS.getKind() == ConversionSpecifier::OutIntPtrArg) { + S.Diag(getLocationOfByte(CS.getStart()), diag::warn_printf_write_back) + << getFormatSpecifierRange(startSpecifier, specifierLen); + // Continue checking the other format specifiers. + return true; + } - // CHECK: Are we using "%n"? Issue a warning. - case 'n': { - ++numConversions; - CurrentState = state_OrdChr; - SourceLocation Loc = getLocationOfStringLiteralByte(FExpr, - LastConversionIdx); + 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); + } - Diag(Loc, diag::warn_printf_write_back)<<OrigFormatExpr->getSourceRange(); - break; - } + // The remaining checks depend on the data arguments. + if (HasVAListArg) + return true; - // Handle "%@" - case '@': - // %@ is allowed in ObjC format strings only. - if (ObjCFExpr != NULL) - CurrentState = state_OrdChr; - else { - // Issue a warning: invalid format conversion. - SourceLocation Loc = - getLocationOfStringLiteralByte(FExpr, LastConversionIdx); - - Diag(Loc, diag::warn_printf_invalid_conversion) - << std::string(Str+LastConversionIdx, - Str+std::min(LastConversionIdx+2, StrLen)) - << OrigFormatExpr->getSourceRange(); - } - ++numConversions; - break; + if (NumConversions > NumDataArgs) { + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_insufficient_data_args) + << getFormatSpecifierRange(startSpecifier, specifierLen); + // Don't do any more checking. + return false; + } - // Handle "%%" - case '%': - // Sanity check: Was the first "%" character the previous one? - // If not, we will assume that we have a malformed format - // conversion, and that the current "%" character is the start - // of a new conversion. - if (StrIdx - LastConversionIdx == 1) - CurrentState = state_OrdChr; - else { - // Issue a warning: invalid format conversion. - SourceLocation Loc = - getLocationOfStringLiteralByte(FExpr, LastConversionIdx); - - Diag(Loc, diag::warn_printf_invalid_conversion) - << std::string(Str+LastConversionIdx, Str+StrIdx) - << OrigFormatExpr->getSourceRange(); - - // This conversion is broken. Advance to the next format - // conversion. - LastConversionIdx = StrIdx; - ++numConversions; - } - break; + // Now type check the data expression that matches the + // format specifier. + const Expr *Ex = getDataArg(NumConversions); + const analyze_printf::ArgTypeResult &ATR = FS.getArgType(S.Context); + if (ATR.isValid() && !ATR.matchesType(S.Context, Ex->getType())) { + // Check if we didn't match because of an implicit cast from a 'char' + // or 'short' to an 'int'. This is done because printf is a varargs + // function. + if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Ex)) + if (ICE->getType() == S.Context.IntTy) + if (ATR.matchesType(S.Context, ICE->getSubExpr()->getType())) + return true; - default: - // This case catches all other characters: flags, widths, etc. - // We should eventually process those as well. - break; - } + S.Diag(getLocationOfByte(CS.getStart()), + diag::warn_printf_conversion_argument_type_mismatch) + << ATR.getRepresentativeType(S.Context) << Ex->getType() + << getFormatSpecifierRange(startSpecifier, specifierLen) + << Ex->getSourceRange(); } - if (CurrentState == state_Conversion) { - // Issue a warning: invalid format conversion. - SourceLocation Loc = - getLocationOfStringLiteralByte(FExpr, LastConversionIdx); + return true; +} - Diag(Loc, diag::warn_printf_invalid_conversion) - << std::string(Str+LastConversionIdx, - Str+std::min(LastConversionIdx+2, StrLen)) - << OrigFormatExpr->getSourceRange(); +void CheckPrintfHandler::DoneProcessing() { + // Does the number of data arguments exceed the number of + // format conversions in the format string? + if (!HasVAListArg && NumConversions < NumDataArgs) + S.Diag(getDataArg(NumConversions+1)->getLocStart(), + diag::warn_printf_too_many_data_args) + << getFormatStringRange(); +} + +void Sema::CheckPrintfString(const StringLiteral *FExpr, + const Expr *OrigFormatExpr, + const CallExpr *TheCall, bool HasVAListArg, + unsigned format_idx, unsigned firstDataArg) { + + // CHECK: is the format string a wide literal? + if (FExpr->isWide()) { + Diag(FExpr->getLocStart(), + diag::warn_printf_format_string_is_wide_literal) + << OrigFormatExpr->getSourceRange(); return; } - if (!HasVAListArg) { - // CHECK: Does the number of format conversions exceed the number - // of data arguments? - if (numConversions > numDataArgs) { - SourceLocation Loc = - getLocationOfStringLiteralByte(FExpr, LastConversionIdx); - - Diag(Loc, diag::warn_printf_insufficient_data_args) - << OrigFormatExpr->getSourceRange(); - } - // CHECK: Does the number of data arguments exceed the number of - // format conversions in the format string? - else if (numConversions < numDataArgs) - Diag(TheCall->getArg(format_idx+numConversions+1)->getLocStart(), - diag::warn_printf_too_many_data_args) - << OrigFormatExpr->getSourceRange(); + // Str - The format string. NOTE: this is NOT null-terminated! + const char *Str = FExpr->getStrData(); + + // CHECK: empty format string? + unsigned StrLen = FExpr->getByteLength(); + + if (StrLen == 0) { + Diag(FExpr->getLocStart(), diag::warn_printf_empty_format_string) + << OrigFormatExpr->getSourceRange(); + return; } + + CheckPrintfHandler H(*this, FExpr, OrigFormatExpr, + TheCall->getNumArgs() - firstDataArg, + isa<ObjCStringLiteral>(OrigFormatExpr), Str, + HasVAListArg, TheCall, format_idx); + + if (!analyze_printf::ParseFormatString(H, Str, Str + StrLen)) + H.DoneProcessing(); } //===--- CHECK: Return Address of Stack Variable --------------------------===// @@ -1300,11 +1366,11 @@ Sema::CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, if (C->hasBlockDeclRefExprs()) Diag(C->getLocStart(), diag::err_ret_local_block) << C->getSourceRange(); - + if (AddrLabelExpr *ALE = dyn_cast<AddrLabelExpr>(RetValExp)) Diag(ALE->getLocStart(), diag::warn_ret_addr_label) << ALE->getSourceRange(); - + } else if (lhsType->isReferenceType()) { // Perform checking for stack values returned by reference. // Check for a reference to the stack @@ -1780,7 +1846,7 @@ IntRange GetExprRange(ASTContext &C, Expr *E, unsigned MaxWidth) { if (BO->getLHS()->getType()->isPointerType()) return IntRange::forType(C, E->getType()); // fallthrough - + default: break; } @@ -2221,7 +2287,7 @@ void Sema::CheckUnreachable(AnalysisContext &AC) { CFG *cfg = AC.getCFG(); if (cfg == 0) return; - + llvm::BitVector live(cfg->getNumBlockIDs()); // Mark all live things first. count = MarkLive(&cfg->getEntry(), live); @@ -2268,7 +2334,9 @@ void Sema::CheckUnreachable(AnalysisContext &AC) { CFGBlock &b = **I; if (!live[b.getBlockID()]) // Avoid excessive errors by marking everything reachable from here - lines.push_back(ErrLoc(MarkLiveTop(&b, live, Context.getSourceManager()), SourceRange(), SourceRange())); + lines.push_back(ErrLoc(MarkLiveTop(&b, live, + Context.getSourceManager()), + SourceRange(), SourceRange())); } } @@ -2418,17 +2486,19 @@ void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body, // which this code would then warn about. if (getDiagnostics().hasErrorOccurred()) return; - + bool ReturnsVoid = false; bool HasNoReturn = false; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - // If the result type of the function is a dependent type, we don't know - // whether it will be void or not, so don't - if (FD->getResultType()->isDependentType()) + // For function templates, class templates and member function templates + // we'll do the analysis at instantiation time. + if (FD->isDependentContext()) return; + if (FD->getResultType()->isVoidType()) ReturnsVoid = true; - if (FD->hasAttr<NoReturnAttr>()) + if (FD->hasAttr<NoReturnAttr>() || + FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) HasNoReturn = true; } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { if (MD->getResultType()->isVoidType()) @@ -2552,6 +2622,24 @@ bool Sema::CheckParmsForFunctionDef(FunctionDecl *FD) { !Param->isImplicit() && !getLangOptions().CPlusPlus) Diag(Param->getLocation(), diag::err_parameter_name_omitted); + + // C99 6.7.5.3p12: + // If the function declarator is not part of a definition of that + // function, parameters may have incomplete type and may use the [*] + // notation in their sequences of declarator specifiers to specify + // variable length array types. + QualType PType = Param->getOriginalType(); + if (const ArrayType *AT = Context.getAsArrayType(PType)) { + if (AT->getSizeModifier() == ArrayType::Star) { + // FIXME: This diagnosic should point the the '[*]' if source-location + // information is added for it. + Diag(Param->getLocation(), diag::err_array_star_in_function_definition); + } + } + + if (getLangOptions().CPlusPlus) + if (const RecordType *RT = Param->getType()->getAs<RecordType>()) + FinalizeVarWithDestructor(Param, RT); } return HasInvalidParm; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index fcd419b..a862949 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -2196,13 +2196,15 @@ void Sema::CodeCompleteCase(Scope *S) { namespace { struct IsBetterOverloadCandidate { Sema &S; + SourceLocation Loc; public: - explicit IsBetterOverloadCandidate(Sema &S) : S(S) { } + explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc) + : S(S), Loc(Loc) { } bool operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { - return S.isBetterOverloadCandidate(X, Y); + return S.isBetterOverloadCandidate(X, Y, Loc); } }; } @@ -2228,7 +2230,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, } // Build an overload candidate set based on the functions we find. - OverloadCandidateSet CandidateSet; + SourceLocation Loc = Fn->getExprLoc(); + OverloadCandidateSet CandidateSet(Loc); // FIXME: What if we're calling something that isn't a function declaration? // FIXME: What if we're calling a pseudo-destructor? @@ -2247,7 +2250,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, if (!FDecl->getType()->getAs<FunctionProtoType>()) Results.push_back(ResultCandidate(FDecl)); else - AddOverloadCandidate(FDecl, Args, NumArgs, CandidateSet, + // FIXME: access? + AddOverloadCandidate(FDecl, AS_none, Args, NumArgs, CandidateSet, false, false, /*PartialOverloading*/ true); } } @@ -2255,7 +2259,7 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn, if (!CandidateSet.empty()) { // Sort the overload candidate set by placing the best overloads first. std::stable_sort(CandidateSet.begin(), CandidateSet.end(), - IsBetterOverloadCandidate(*this)); + IsBetterOverloadCandidate(*this, Loc)); // Add the remaining viable overload candidates as code-completion reslults. for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), @@ -2977,7 +2981,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - DefaultFunctionArrayConversion(RecExpr); + DefaultFunctionArrayLvalueConversion(RecExpr); QualType ReceiverType = RecExpr->getType(); if (ReceiverType->isObjCIdType() || ReceiverType->isBlockPointerType()) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fbe0289..1fc08ce 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -14,7 +14,7 @@ #include "Sema.h" #include "SemaInit.h" #include "Lookup.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -135,6 +135,7 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, case LookupResult::NotFoundInCurrentInstantiation: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: + Result.suppressDiagnostics(); return 0; case LookupResult::Ambiguous: @@ -509,9 +510,18 @@ static void RemoveUsingDecls(LookupResult &R) { } static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { + if (D->isInvalidDecl()) + return false; + if (D->isUsed() || D->hasAttr<UnusedAttr>()) return false; - + + // White-list anything that isn't a local variable. + if (!isa<VarDecl>(D) || isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) || + !D->getDeclContext()->isFunctionOrMethod()) + return false; + + // Types of valid local variables should be complete, so this should succeed. if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { @@ -523,9 +533,7 @@ static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) { } } - return (isa<VarDecl>(D) && !isa<ParmVarDecl>(D) && - !isa<ImplicitParamDecl>(D) && - D->getDeclContext()->isFunctionOrMethod()); + return true; } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { @@ -690,7 +698,7 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Params.push_back(ParmVarDecl::Create(Context, New, SourceLocation(), 0, FT->getArgType(i), /*TInfo=*/0, VarDecl::None, 0)); - New->setParams(Context, Params.data(), Params.size()); + New->setParams(Params.data(), Params.size()); } AddKnownFunctionAttributes(New); @@ -957,6 +965,44 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { return true; } + // If a function is first declared with a calling convention, but is + // later declared or defined without one, the second decl assumes the + // calling convention of the first. + // + // For the new decl, we have to look at the NON-canonical type to tell the + // difference between a function that really doesn't have a calling + // convention and one that is declared cdecl. That's because in + // canonicalization (see ASTContext.cpp), cdecl is canonicalized away + // because it is the default calling convention. + // + // Note also that we DO NOT return at this point, because we still have + // other tests to run. + const FunctionType *OldType = OldQType->getAs<FunctionType>(); + const FunctionType *NewType = New->getType()->getAs<FunctionType>(); + if (OldType->getCallConv() != CC_Default && + NewType->getCallConv() == CC_Default) { + NewQType = Context.getCallConvType(NewQType, OldType->getCallConv()); + New->setType(NewQType); + NewQType = Context.getCanonicalType(NewQType); + } else if (!Context.isSameCallConv(OldType->getCallConv(), + NewType->getCallConv())) { + // Calling conventions really aren't compatible, so complain. + Diag(New->getLocation(), diag::err_cconv_change) + << FunctionType::getNameForCallConv(NewType->getCallConv()) + << (OldType->getCallConv() == CC_Default) + << (OldType->getCallConv() == CC_Default ? "" : + FunctionType::getNameForCallConv(OldType->getCallConv())); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; + } + + // FIXME: diagnose the other way around? + if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) { + NewQType = Context.getNoReturnType(NewQType); + New->setType(NewQType); + assert(NewQType.isCanonical()); + } + if (getLangOptions().CPlusPlus) { // (C++98 13.1p2): // Certain function declarations cannot be overloaded: @@ -1061,7 +1107,7 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { Params.push_back(Param); } - New->setParams(Context, Params.data(), Params.size()); + New->setParams(Params.data(), Params.size()); } return MergeCompatibleFunctionDecls(New, Old); @@ -1297,6 +1343,18 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { Diag(Old->getLocation(), diag::note_previous_definition); } + // C++ doesn't have tentative definitions, so go right ahead and check here. + const VarDecl *Def; + if (getLangOptions().CPlusPlus && + New->isThisDeclarationADefinition() == VarDecl::Definition && + (Def = Old->getDefinition())) { + Diag(New->getLocation(), diag::err_redefinition) + << New->getDeclName(); + Diag(Def->getLocation(), diag::note_previous_definition); + New->setInvalidDecl(); + return; + } + // Keep a chain of previous declarations. New->setPreviousDeclaration(Old); @@ -1855,6 +1913,13 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, if (!DC->isDependentContext() && RequireCompleteDeclContext(D.getCXXScopeSpec())) return DeclPtrTy(); + + if (isa<CXXRecordDecl>(DC) && !cast<CXXRecordDecl>(DC)->hasDefinition()) { + Diag(D.getIdentifierLoc(), + diag::err_member_def_undefined_record) + << Name << DC << D.getCXXScopeSpec().getRange(); + D.setInvalidType(); + } LookupQualifiedName(Previous, DC); @@ -2322,7 +2387,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewVD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); + NewVD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); } // Don't consider existing declarations that are in a different @@ -2359,9 +2424,9 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, // attributes declared post-definition are currently ignored if (Previous.isSingleResult()) { - const VarDecl *Def = 0; - VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl()); - if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) { + VarDecl *Def = dyn_cast<VarDecl>(Previous.getFoundDecl()); + if (Def && (Def = Def->getDefinition()) && + Def != NewVD && D.hasAttributes()) { Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition); Diag(Def->getLocation(), diag::note_previous_definition); } @@ -2675,7 +2740,8 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // (The parser checks for a return type and makes the declarator a // constructor if it has no return type). // must have an invalid constructor that has a return type - if (Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ + if (Name.getAsIdentifierInfo() && + Name.getAsIdentifierInfo() == cast<CXXRecordDecl>(DC)->getIdentifier()){ Diag(D.getIdentifierLoc(), diag::err_constructor_return_type) << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) << SourceRange(D.getIdentifierLoc()); @@ -2783,6 +2849,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } } + // C++ [dcl.fct.spec]p6: + // The explicit specifier shall be used only in the declaration of a + // constructor or conversion function within its class definition; see 12.3.1 + // and 12.3.2. + if (isExplicit && !NewFD->isInvalidDecl()) { + if (!CurContext->isRecord()) { + // 'explicit' was specified outside of the class. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_out_of_class) + << CodeModificationHint::CreateRemoval( + D.getDeclSpec().getExplicitSpecLoc()); + } else if (!isa<CXXConstructorDecl>(NewFD) && + !isa<CXXConversionDecl>(NewFD)) { + // 'explicit' was specified on a function that wasn't a constructor + // or conversion function. + Diag(D.getDeclSpec().getExplicitSpecLoc(), + diag::err_explicit_non_ctor_or_conv_function) + << CodeModificationHint::CreateRemoval( + D.getDeclSpec().getExplicitSpecLoc()); + } + } + // Filter out previous declarations that don't match the scope. FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage()); @@ -2822,7 +2910,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(::new (Context) AsmLabelAttr(SE->getString())); + NewFD->addAttr(::new (Context) AsmLabelAttr(Context, SE->getString())); } // Copy the parameter declarations from the declarator D to the function @@ -2882,7 +2970,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, "Should not need args for typedef of non-prototype fn"); } // Finally, we know we have the right number of parameters, install them. - NewFD->setParams(Context, Params.data(), Params.size()); + NewFD->setParams(Params.data(), Params.size()); // If the declarator is a template-id, translate the parser's template // argument list into our AST format. @@ -2950,7 +3038,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // Fake up an access specifier if it's supposed to be a class member. - if (isa<CXXRecordDecl>(NewFD->getDeclContext())) + if (!Redeclaration && isa<CXXRecordDecl>(NewFD->getDeclContext())) NewFD->setAccess(AS_public); // An out-of-line member function declaration must also be a @@ -3041,6 +3129,15 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (FunctionTemplate) return FunctionTemplate; + + // Keep track of static, non-inlined function definitions that + // have not been used. We will warn later. + // FIXME: Also include static functions declared but not defined. + if (!NewFD->isInvalidDecl() && IsFunctionDefinition + && !NewFD->isInlined() && NewFD->getLinkage() == InternalLinkage + && !NewFD->isUsed()) + UnusedStaticFuncs.push_back(NewFD); + return NewFD; } @@ -3412,8 +3509,8 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { AbstractVariableType)) VDecl->setInvalidDecl(); - const VarDecl *Def = 0; - if (VDecl->getDefinition(Def)) { + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); @@ -3473,7 +3570,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { // }; // Attach the initializer - VDecl->setInit(Context, Init); + VDecl->setInit(Init); // C++ [class.mem]p4: // A member-declarator can contain a constant-initializer only @@ -3545,23 +3642,15 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) { Init = MaybeCreateCXXExprWithTemporaries(Init); // Attach the initializer to the decl. - VDecl->setInit(Context, Init); - - // If the previous declaration of VDecl was a tentative definition, - // remove it from the set of tentative definitions. - if (VDecl->getPreviousDeclaration() && - VDecl->getPreviousDeclaration()->isTentativeDefinition(Context)) { - bool Deleted = TentativeDefinitions.erase(VDecl->getDeclName()); - assert(Deleted && "Unrecorded tentative definition?"); Deleted=Deleted; - } + VDecl->setInit(Init); if (getLangOptions().CPlusPlus) { // Make sure we mark the destructor as used if necessary. QualType InitType = VDecl->getType(); while (const ArrayType *Array = Context.getAsArrayType(InitType)) InitType = Context.getBaseElementType(Array); - if (InitType->isRecordType()) - FinalizeVarWithDestructor(VDecl, InitType); + if (const RecordType *Record = InitType->getAs<RecordType>()) + FinalizeVarWithDestructor(VDecl, Record); } return; @@ -3578,136 +3667,140 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl, if (VarDecl *Var = dyn_cast<VarDecl>(RealDecl)) { QualType Type = Var->getType(); - // Record tentative definitions. - if (Var->isTentativeDefinition(Context)) { - std::pair<llvm::DenseMap<DeclarationName, VarDecl *>::iterator, bool> - InsertPair = - TentativeDefinitions.insert(std::make_pair(Var->getDeclName(), Var)); + // C++0x [dcl.spec.auto]p3 + if (TypeContainsUndeducedAuto) { + Diag(Var->getLocation(), diag::err_auto_var_requires_init) + << Var->getDeclName() << Type; + Var->setInvalidDecl(); + return; + } + + switch (Var->isThisDeclarationADefinition()) { + case VarDecl::Definition: + if (!Var->isStaticDataMember() || !Var->getAnyInitializer()) + break; - // Keep the latest definition in the map. If we see 'int i; int i;' we - // want the second one in the map. - InsertPair.first->second = Var; + // We have an out-of-line definition of a static data member + // that has an in-class initializer, so we type-check this like + // a declaration. + // + // Fall through + + case VarDecl::DeclarationOnly: + // It's only a declaration. + + // Block scope. C99 6.7p7: If an identifier for an object is + // declared with no linkage (C99 6.2.2p6), the type for the + // object shall be complete. + if (!Type->isDependentType() && Var->isBlockVarDecl() && + !Var->getLinkage() && !Var->isInvalidDecl() && + RequireCompleteType(Var->getLocation(), Type, + diag::err_typecheck_decl_incomplete_type)) + Var->setInvalidDecl(); - // However, for the list, we don't care about the order, just make sure - // that there are no dupes for a given declaration name. - if (InsertPair.second) - TentativeDefinitionList.push_back(Var->getDeclName()); + // Make sure that the type is not abstract. + if (!Type->isDependentType() && !Var->isInvalidDecl() && + RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) + Var->setInvalidDecl(); + return; + + case VarDecl::TentativeDefinition: + // File scope. C99 6.9.2p2: A declaration of an identifier for an + // object that has file scope without an initializer, and without a + // storage-class specifier or with the storage-class specifier "static", + // constitutes a tentative definition. Note: A tentative definition with + // external linkage is valid (C99 6.2.2p5). + if (!Var->isInvalidDecl()) { + if (const IncompleteArrayType *ArrayT + = Context.getAsIncompleteArrayType(Type)) { + if (RequireCompleteType(Var->getLocation(), + ArrayT->getElementType(), + diag::err_illegal_decl_array_incomplete_type)) + Var->setInvalidDecl(); + } else if (Var->getStorageClass() == VarDecl::Static) { + // C99 6.9.2p3: If the declaration of an identifier for an object is + // a tentative definition and has internal linkage (C99 6.2.2p3), the + // declared type shall not be an incomplete type. + // NOTE: code such as the following + // static struct s; + // struct s { int a; }; + // is accepted by gcc. Hence here we issue a warning instead of + // an error and we do not invalidate the static declaration. + // NOTE: to avoid multiple warnings, only check the first declaration. + if (Var->getPreviousDeclaration() == 0) + RequireCompleteType(Var->getLocation(), Type, + diag::ext_typecheck_decl_incomplete_type); + } + } + + // Record the tentative definition; we're done. + if (!Var->isInvalidDecl()) + TentativeDefinitions.push_back(Var); + return; } - // C++ [dcl.init.ref]p3: - // The initializer can be omitted for a reference only in a - // parameter declaration (8.3.5), in the declaration of a - // function return type, in the declaration of a class member - // within its class declaration (9.2), and where the extern - // specifier is explicitly used. - if (Type->isReferenceType() && !Var->hasExternalStorage()) { - Diag(Var->getLocation(), diag::err_reference_var_requires_init) - << Var->getDeclName() - << SourceRange(Var->getLocation(), Var->getLocation()); + // Provide a specific diagnostic for uninitialized variable + // definitions with incomplete array type. + if (Type->isIncompleteArrayType()) { + Diag(Var->getLocation(), + diag::err_typecheck_incomplete_array_needs_initializer); Var->setInvalidDecl(); return; } - // C++0x [dcl.spec.auto]p3 - if (TypeContainsUndeducedAuto) { - Diag(Var->getLocation(), diag::err_auto_var_requires_init) - << Var->getDeclName() << Type; + // Provide a specific diagnostic for uninitialized variable + // definitions with reference type. + if (Type->isReferenceType()) { + Diag(Var->getLocation(), diag::err_reference_var_requires_init) + << Var->getDeclName() + << SourceRange(Var->getLocation(), Var->getLocation()); + Var->setInvalidDecl(); + return; + } + + // Do not attempt to type-check the default initializer for a + // variable with dependent type. + if (Type->isDependentType()) + return; + + if (Var->isInvalidDecl()) + return; + + if (RequireCompleteType(Var->getLocation(), + Context.getBaseElementType(Type), + diag::err_typecheck_decl_incomplete_type)) { Var->setInvalidDecl(); return; } - // An array without size is an incomplete type, and there are no special - // rules in C++ to make such a definition acceptable. - if (getLangOptions().CPlusPlus && Type->isIncompleteArrayType() && - !Var->hasExternalStorage()) { - Diag(Var->getLocation(), - diag::err_typecheck_incomplete_array_needs_initializer); + // The variable can not have an abstract class type. + if (RequireNonAbstractType(Var->getLocation(), Type, + diag::err_abstract_type_in_decl, + AbstractVariableType)) { Var->setInvalidDecl(); return; } - // C++ [temp.expl.spec]p15: - // An explicit specialization of a static data member of a template is a - // definition if the declaration includes an initializer; otherwise, it - // is a declaration. - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember() && - Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return; + InitializedEntity Entity = InitializedEntity::InitializeVariable(Var); + InitializationKind Kind + = InitializationKind::CreateDefault(Var->getLocation()); - // C++ [dcl.init]p9: - // If no initializer is specified for an object, and the object - // is of (possibly cv-qualified) non-POD class type (or array - // thereof), the object shall be default-initialized; if the - // object is of const-qualified type, the underlying class type - // shall have a user-declared default constructor. - // - // FIXME: Diagnose the "user-declared default constructor" bit. - if (getLangOptions().CPlusPlus) { - QualType InitType = Type; - if (const ArrayType *Array = Context.getAsArrayType(Type)) - InitType = Context.getBaseElementType(Array); - if ((!Var->hasExternalStorage() && !Var->isExternC()) && - InitType->isRecordType() && !InitType->isDependentType()) { - if (!RequireCompleteType(Var->getLocation(), InitType, - diag::err_invalid_incomplete_type_use)) { - InitializedEntity Entity - = InitializedEntity::InitializeVariable(Var); - InitializationKind Kind - = InitializationKind::CreateDefault(Var->getLocation()); - - InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); - OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, 0, 0)); - if (Init.isInvalid()) - Var->setInvalidDecl(); - else { - Var->setInit(Context, - MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - FinalizeVarWithDestructor(Var, InitType); - } - } else { - Var->setInvalidDecl(); - } - } + InitializationSequence InitSeq(*this, Entity, Kind, 0, 0); + OwningExprResult Init = InitSeq.Perform(*this, Entity, Kind, + MultiExprArg(*this, 0, 0)); + if (Init.isInvalid()) + Var->setInvalidDecl(); + else { + if (Init.get()) + Var->setInit(MaybeCreateCXXExprWithTemporaries(Init.takeAs<Expr>())); - // The variable can not have an abstract class type. - if (RequireNonAbstractType(Var->getLocation(), Type, - diag::err_abstract_type_in_decl, - AbstractVariableType)) - Var->setInvalidDecl(); + if (getLangOptions().CPlusPlus) + if (const RecordType *Record + = Context.getBaseElementType(Type)->getAs<RecordType>()) + FinalizeVarWithDestructor(Var, Record); } - -#if 0 - // FIXME: Temporarily disabled because we are not properly parsing - // linkage specifications on declarations, e.g., - // - // extern "C" const CGPoint CGPointerZero; - // - // C++ [dcl.init]p9: - // - // If no initializer is specified for an object, and the - // object is of (possibly cv-qualified) non-POD class type (or - // array thereof), the object shall be default-initialized; if - // the object is of const-qualified type, the underlying class - // type shall have a user-declared default - // constructor. Otherwise, if no initializer is specified for - // an object, the object and its subobjects, if any, have an - // indeterminate initial value; if the object or any of its - // subobjects are of const-qualified type, the program is - // ill-formed. - // - // This isn't technically an error in C, so we don't diagnose it. - // - // FIXME: Actually perform the POD/user-defined default - // constructor check. - if (getLangOptions().CPlusPlus && - Context.getCanonicalType(Type).isConstQualified() && - !Var->hasExternalStorage()) - Diag(Var->getLocation(), diag::err_const_var_requires_init) - << Var->getName() - << SourceRange(Var->getLocation(), Var->getLocation()); -#endif } } @@ -3723,77 +3816,6 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, if (Decl *D = Group[i].getAs<Decl>()) Decls.push_back(D); - // Perform semantic analysis that depends on having fully processed both - // the declarator and initializer. - for (unsigned i = 0, e = Decls.size(); i != e; ++i) { - VarDecl *IDecl = dyn_cast<VarDecl>(Decls[i]); - if (!IDecl) - continue; - QualType T = IDecl->getType(); - - // Block scope. C99 6.7p7: If an identifier for an object is declared with - // no linkage (C99 6.2.2p6), the type for the object shall be complete... - if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) { - if (T->isDependentType()) { - // If T is dependent, we should not require a complete type. - // (RequireCompleteType shouldn't be called with dependent types.) - // But we still can at least check if we've got an array of unspecified - // size without an initializer. - if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() && - !IDecl->getInit()) { - Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type) - << T; - IDecl->setInvalidDecl(); - } - } else if (!IDecl->isInvalidDecl()) { - // If T is an incomplete array type with an initializer list that is - // dependent on something, its size has not been fixed. We could attempt - // to fix the size for such arrays, but we would still have to check - // here for initializers containing a C++0x vararg expansion, e.g. - // template <typename... Args> void f(Args... args) { - // int vals[] = { args }; - // } - const IncompleteArrayType *IAT = Context.getAsIncompleteArrayType(T); - Expr *Init = IDecl->getInit(); - if (IAT && Init && - (Init->isTypeDependent() || Init->isValueDependent())) { - // Check that the member type of the array is complete, at least. - if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(), - diag::err_typecheck_decl_incomplete_type)) - IDecl->setInvalidDecl(); - } else if (RequireCompleteType(IDecl->getLocation(), T, - diag::err_typecheck_decl_incomplete_type)) - IDecl->setInvalidDecl(); - } - } - // File scope. C99 6.9.2p2: A declaration of an identifier for an - // object that has file scope without an initializer, and without a - // storage-class specifier or with the storage-class specifier "static", - // constitutes a tentative definition. Note: A tentative definition with - // external linkage is valid (C99 6.2.2p5). - if (IDecl->isTentativeDefinition(Context) && !IDecl->isInvalidDecl()) { - if (const IncompleteArrayType *ArrayT - = Context.getAsIncompleteArrayType(T)) { - if (RequireCompleteType(IDecl->getLocation(), - ArrayT->getElementType(), - diag::err_illegal_decl_array_incomplete_type)) - IDecl->setInvalidDecl(); - } else if (IDecl->getStorageClass() == VarDecl::Static) { - // C99 6.9.2p3: If the declaration of an identifier for an object is - // a tentative definition and has internal linkage (C99 6.2.2p3), the - // declared type shall not be an incomplete type. - // NOTE: code such as the following - // static struct s; - // struct s { int a; }; - // is accepted by gcc. Hence here we issue a warning instead of - // an error and we do not invalidate the static declaration. - // NOTE: to avoid multiple warnings, only check the first declaration. - if (IDecl->getPreviousDeclaration() == 0) - RequireCompleteType(IDecl->getLocation(), T, - diag::ext_typecheck_decl_incomplete_type); - } - } - } return DeclGroupPtrTy::make(DeclGroupRef::Create(Context, Decls.data(), Decls.size())); } @@ -3853,6 +3875,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { // Recover by removing the name II = 0; D.SetIdentifier(0, D.getIdentifierLoc()); + D.setInvalidType(true); } } } @@ -3919,6 +3942,11 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { return DeclPtrTy::make(New); } +void Sema::ActOnObjCCatchParam(DeclPtrTy D) { + ParmVarDecl *Param = cast<ParmVarDecl>(D.getAs<Decl>()); + Param->setDeclContext(CurContext); +} + void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls) { assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && @@ -4297,8 +4325,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1, - HasVAListArg ? 0 : FormatIdx + 2)); + FD->addAttr(::new (Context) FormatAttr(Context, "printf", FormatIdx+1, + HasVAListArg ? 0 : FormatIdx+2)); } // Mark const if we don't care about errno and that is the only @@ -4311,7 +4339,7 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { } if (Context.BuiltinInfo.isNoReturn(BuiltinID)) - FD->addAttr(::new (Context) NoReturnAttr()); + FD->setType(Context.getNoReturnType(FD->getType())); if (Context.BuiltinInfo.isNoThrow(BuiltinID)) FD->addAttr(::new (Context) NoThrowAttr()); if (Context.BuiltinInfo.isConst(BuiltinID)) @@ -4335,15 +4363,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // FIXME: NSLog and NSLogv should be target specific if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { // FIXME: We known better than our headers. - const_cast<FormatAttr *>(Format)->setType("printf"); + const_cast<FormatAttr *>(Format)->setType(Context, "printf"); } else - FD->addAttr(::new (Context) FormatAttr("printf", 1, + FD->addAttr(::new (Context) FormatAttr(Context, "printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { // FIXME: asprintf and vasprintf aren't C99 functions. Should they be // target-specific builtins, perhaps? if (!FD->getAttr<FormatAttr>()) - FD->addAttr(::new (Context) FormatAttr("printf", 2, + FD->addAttr(::new (Context) FormatAttr(Context, "printf", 2, Name->isStr("vasprintf") ? 0 : 3)); } } @@ -4614,7 +4642,7 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Diagnose attempts to redefine a tag. if (TUK == TUK_Definition) { - if (TagDecl *Def = PrevTagDecl->getDefinition(Context)) { + if (TagDecl *Def = PrevTagDecl->getDefinition()) { // If we're defining a specialization and the previous definition // is from an implicit instantiation, don't emit an error // here; we'll catch this in the general case below. @@ -4927,9 +4955,17 @@ RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record, if (Record->isDependentContext() || !Record->isDefinition()) return; - if (Record->isDynamicClass() && !S.Context.getKeyFunction(Record)) - S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc)); + if (Record->isDynamicClass()) { + const CXXMethodDecl *KeyFunction = S.Context.getKeyFunction(Record); + if (!KeyFunction) + S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, + Loc)); + + if ((!KeyFunction || (KeyFunction->getBody() && KeyFunction->isInlined())) + && Record->getLinkage() == ExternalLinkage) + S.Diag(Record->getLocation(), diag::warn_weak_vtable) << Record; + } for (DeclContext::decl_iterator D = Record->decls_begin(), DEnd = Record->decls_end(); D != DEnd; ++D) { @@ -5156,7 +5192,7 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, NewFD->setInvalidDecl(); } - if (getLangOptions().CPlusPlus) { + if (!InvalidDecl && getLangOptions().CPlusPlus) { CXXRecordDecl* CXXRecord = cast<CXXRecordDecl>(Record); if (!T->isPODType()) @@ -5584,7 +5620,7 @@ void Sema::ActOnFields(Scope* S, // Okay, we successfully defined 'Record'. if (Record) { - Record->completeDefinition(Context); + Record->completeDefinition(); } else { ObjCIvarDecl **ClsFields = reinterpret_cast<ObjCIvarDecl**>(RecFields.data()); @@ -5628,6 +5664,45 @@ void Sema::ActOnFields(Scope* S, ProcessDeclAttributeList(S, Record, Attr); } +/// \brief Determine whether the given integral value is representable within +/// the given type T. +static bool isRepresentableIntegerValue(ASTContext &Context, + llvm::APSInt &Value, + QualType T) { + assert(T->isIntegralType() && "Integral type required!"); + unsigned BitWidth = Context.getTypeSize(T); + + if (Value.isUnsigned() || Value.isNonNegative()) + return Value.getActiveBits() < BitWidth; + + return Value.getMinSignedBits() <= BitWidth; +} + +// \brief Given an integral type, return the next larger integral type +// (or a NULL type of no such type exists). +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!"); + const unsigned NumTypes = 4; + QualType SignedIntegralTypes[NumTypes] = { + Context.ShortTy, Context.IntTy, Context.LongTy, Context.LongLongTy + }; + QualType UnsignedIntegralTypes[NumTypes] = { + Context.UnsignedShortTy, Context.UnsignedIntTy, Context.UnsignedLongTy, + Context.UnsignedLongLongTy + }; + + unsigned BitWidth = Context.getTypeSize(T); + QualType *Types = T->isSignedIntegerType()? SignedIntegralTypes + : UnsignedIntegralTypes; + for (unsigned I = 0; I != NumTypes; ++I) + if (Context.getTypeSize(Types[I]) > BitWidth) + return Types[I]; + + return QualType(); +} + EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, EnumConstantDecl *LastEnumConst, SourceLocation IdLoc, @@ -5635,24 +5710,45 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, ExprArg val) { Expr *Val = (Expr *)val.get(); - llvm::APSInt EnumVal(32); + unsigned IntWidth = Context.Target.getIntWidth(); + llvm::APSInt EnumVal(IntWidth); QualType EltTy; if (Val) { if (Enum->isDependentType()) EltTy = Context.DependentTy; else { - // Make sure to promote the operand type to int. - UsualUnaryConversions(Val); - if (Val != val.get()) { - val.release(); - val = Val; - } - // C99 6.7.2.2p2: Make sure we have an integer constant expression. SourceLocation ExpLoc; if (VerifyIntegerConstantExpression(Val, &EnumVal)) { Val = 0; - } else { + } else { + if (!getLangOptions().CPlusPlus) { + // C99 6.7.2.2p2: + // The expression that defines the value of an enumeration constant + // shall be an integer constant expression that has a value + // representable as an int. + + // Complain if the value is not representable in an int. + if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << Val->getSourceRange() + << EnumVal.isNonNegative(); + else if (!Context.hasSameType(Val->getType(), Context.IntTy)) { + // Force the type of the expression to 'int'. + ImpCastExprToType(Val, Context.IntTy, CastExpr::CK_IntegralCast); + + if (Val != val.get()) { + val.release(); + val = Val; + } + } + } + + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If an initializer is specified for an enumerator, the + // initializing value has the same type as the expression. EltTy = Val->getType(); } } @@ -5661,25 +5757,76 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, if (!Val) { if (Enum->isDependentType()) EltTy = Context.DependentTy; - else if (LastEnumConst) { + else if (!LastEnumConst) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // - If no initializer is specified for the first enumerator, the + // initializing value has an unspecified integral type. + // + // GCC uses 'int' for its unspecified integral type, as does + // C99 6.7.2.2p3. + EltTy = Context.IntTy; + } else { // Assign the last value + 1. EnumVal = LastEnumConst->getInitVal(); ++EnumVal; + EltTy = LastEnumConst->getType(); // Check for overflow on increment. - if (EnumVal < LastEnumConst->getInitVal()) - Diag(IdLoc, diag::warn_enum_value_overflow); - - EltTy = LastEnumConst->getType(); - } else { - // First value, set to zero. - EltTy = Context.IntTy; - EnumVal.zextOrTrunc(static_cast<uint32_t>(Context.getTypeSize(EltTy))); - EnumVal.setIsSigned(true); + if (EnumVal < LastEnumConst->getInitVal()) { + // C++0x [dcl.enum]p5: + // If the underlying type is not fixed, the type of each enumerator + // is the type of its initializing value: + // + // - Otherwise the type of the initializing value is the same as + // the type of the initializing value of the preceding enumerator + // unless the incremented value is not representable in that type, + // in which case the type is an unspecified integral type + // sufficient to contain the incremented value. If no such type + // exists, the program is ill-formed. + QualType T = getNextLargerIntegralType(Context, EltTy); + if (T.isNull()) { + // There is no integral type larger enough to represent this + // value. Complain, then allow the value to wrap around. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.zext(EnumVal.getBitWidth() * 2); + Diag(IdLoc, diag::warn_enumerator_too_large) + << EnumVal.toString(10); + } else { + EltTy = T; + } + + // Retrieve the last enumerator's value, extent that type to the + // type that is supposed to be large enough to represent the incremented + // value, then increment. + EnumVal = LastEnumConst->getInitVal(); + EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); + ++EnumVal; + + // If we're not in C++, diagnose the overflow of enumerator values, + // which in C99 means that the enumerator value is not representable in + // an int (C99 6.7.2.2p2). However, we support GCC's extension that + // permits enumerator values that are representable in some larger + // integral type. + if (!getLangOptions().CPlusPlus && !T.isNull()) + Diag(IdLoc, diag::warn_enum_value_overflow); + } else if (!getLangOptions().CPlusPlus && + !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + // Enforce C99 6.7.2.2p2 even when we compute the next value. + Diag(IdLoc, diag::ext_enum_value_not_int) + << EnumVal.toString(10) << 1; + } } } - assert(!EltTy.isNull() && "Enum constant with NULL type"); + if (!Enum->isDependentType()) { + // Make the enumerator value match the signedness and size of the + // enumerator's type. + EnumVal.zextOrTrunc(Context.getTypeSize(EltTy)); + EnumVal.setIsSigned(EltTy->isSignedIntegerType()); + } val.release(); return EnumConstantDecl::Create(Context, Enum, IdLoc, Id, EltTy, @@ -5759,7 +5906,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(EnumType); } - Enum->completeDefinition(Context, Context.DependentTy, Context.DependentTy); + Enum->completeDefinition(Context.DependentTy, Context.DependentTy); return; } @@ -5783,18 +5930,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, cast_or_null<EnumConstantDecl>(Elements[i].getAs<Decl>()); if (!ECD) continue; // Already issued a diagnostic. - // If the enum value doesn't fit in an int, emit an extension warning. const llvm::APSInt &InitVal = ECD->getInitVal(); - assert(InitVal.getBitWidth() >= IntWidth && - "Should have promoted value to int"); - if (!getLangOptions().CPlusPlus && InitVal.getBitWidth() > IntWidth) { - llvm::APSInt V(InitVal); - V.trunc(IntWidth); - V.extend(InitVal.getBitWidth()); - if (V != InitVal) - Diag(ECD->getLocation(), diag::ext_enum_value_not_int) - << InitVal.toString(10); - } // Keep track of the size of positive and negative values. if (InitVal.isUnsigned() || InitVal.isNonNegative()) @@ -5856,8 +5992,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType); } else { - // If there is no negative value, figure out which of uint, ulong, ulonglong - // fits. + // If there is no negative value, figure out the smallest type that fits + // all of the enumerator values. // If it's packed, check also if it fits a char or a short. if (Packed && NumPositiveBits <= CharWidth) { BestType = Context.UnsignedCharTy; @@ -5870,30 +6006,26 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, } else if (NumPositiveBits <= IntWidth) { BestType = Context.UnsignedIntTy; BestWidth = IntWidth; - BestPromotionType = (NumPositiveBits == BestWidth - ? Context.UnsignedIntTy : Context.IntTy); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedIntTy : Context.IntTy; } else if (NumPositiveBits <= (BestWidth = Context.Target.getLongWidth())) { BestType = Context.UnsignedLongTy; - BestPromotionType = (NumPositiveBits == BestWidth - ? Context.UnsignedLongTy : Context.LongTy); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedLongTy : Context.LongTy; } else { BestWidth = Context.Target.getLongLongWidth(); assert(NumPositiveBits <= BestWidth && "How could an initializer get larger than ULL?"); BestType = Context.UnsignedLongLongTy; - BestPromotionType = (NumPositiveBits == BestWidth - ? Context.UnsignedLongLongTy : Context.LongLongTy); + BestPromotionType + = (NumPositiveBits == BestWidth || !getLangOptions().CPlusPlus) + ? Context.UnsignedLongLongTy : Context.LongLongTy; } } - // If we're in C and the promotion type is larger than an int, just - // use the underlying type, which is generally the unsigned integer - // type of the same rank as the promotion type. This is how the gcc - // extension works. - if (!getLangOptions().CPlusPlus && BestPromotionType != Context.IntTy) - BestPromotionType = BestType; - // Loop over all of the enumerator constants, changing their types to match // the type of the enum if needed. for (unsigned i = 0; i != NumElements; ++i) { @@ -5906,23 +6038,17 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, // enumerator value fits in an int, type it as an int, otherwise type it the // same as the enumerator decl itself. This means that in "enum { X = 1U }" // that X has type 'int', not 'unsigned'. - if (!getLangOptions().CPlusPlus && ECD->getType() == Context.IntTy) - continue; // Determine whether the value fits into an int. llvm::APSInt InitVal = ECD->getInitVal(); - bool FitsInInt; - if (InitVal.isUnsigned() || !InitVal.isNegative()) - FitsInInt = InitVal.getActiveBits() < IntWidth; - else - FitsInInt = InitVal.getMinSignedBits() <= IntWidth; // If it fits into an integer type, force it. Otherwise force it to match // the enum decl type. QualType NewTy; unsigned NewWidth; bool NewSign; - if (FitsInInt && !getLangOptions().CPlusPlus) { + if (!getLangOptions().CPlusPlus && + isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) { NewTy = Context.IntTy; NewWidth = IntWidth; NewSign = true; @@ -5960,7 +6086,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, ECD->setType(NewTy); } - Enum->completeDefinition(Context, BestType, BestPromotionType); + Enum->completeDefinition(BestType, BestPromotionType); } Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 1a12208..cba1e9e 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -307,7 +307,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned* start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); std::sort(start, start + size); - d->addAttr(::new (S.Context) NonNullAttr(start, size)); + d->addAttr(::new (S.Context) NonNullAttr(S.Context, start, size)); } static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -329,7 +329,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: check if target symbol exists in current file - d->addAttr(::new (S.Context) AliasAttr(Str->getString())); + d->addAttr(::new (S.Context) AliasAttr(S.Context, Str->getString())); } static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, @@ -391,6 +391,11 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, } static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { + // Don't apply as a decl attribute to ValueDecl. + // FIXME: probably ought to diagnose this. + if (isa<ValueDecl>(d)) + return; + if (HandleCommonNoReturnAttr(d, Attr, S)) d->addAttr(::new (S.Context) NoReturnAttr()); } @@ -404,7 +409,7 @@ static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) - << Attr.getName() << 8; /*function, method, or parameter*/ + << Attr.getName() << 8 /*function, method, or parameter*/; return; } // FIXME: Actually store the attribute on the declaration @@ -542,17 +547,16 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - const char *TypeStr = Str->getStrData(); - unsigned TypeLen = Str->getByteLength(); + llvm::StringRef TypeStr = Str->getString(); VisibilityAttr::VisibilityTypes type; - if (TypeLen == 7 && !memcmp(TypeStr, "default", 7)) + if (TypeStr == "default") type = VisibilityAttr::DefaultVisibility; - else if (TypeLen == 6 && !memcmp(TypeStr, "hidden", 6)) + else if (TypeStr == "hidden") type = VisibilityAttr::HiddenVisibility; - else if (TypeLen == 8 && !memcmp(TypeStr, "internal", 8)) + else if (TypeStr == "internal") type = VisibilityAttr::HiddenVisibility; // FIXME - else if (TypeLen == 9 && !memcmp(TypeStr, "protected", 9)) + else if (TypeStr == "protected") type = VisibilityAttr::ProtectedVisibility; else { S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr; @@ -938,105 +942,9 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(::new (S.Context) SectionAttr(SE->getString())); -} - -static void HandleCDeclAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // Attribute has no arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - - // Attribute can be applied only to functions. - if (!isa<FunctionDecl>(d)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; - return; - } - - // cdecl and fastcall attributes are mutually incompatible. - if (d->getAttr<FastCallAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << "cdecl" << "fastcall"; - return; - } - - // cdecl and stdcall attributes are mutually incompatible. - if (d->getAttr<StdCallAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << "cdecl" << "stdcall"; - return; - } - - d->addAttr(::new (S.Context) CDeclAttr()); -} - - -static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // Attribute has no arguments. - if (Attr.getNumArgs() != 0) { - S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; - } - - // Attribute can be applied only to functions. - if (!isa<FunctionDecl>(d)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << Attr.getName() << 0 /*function*/; - return; - } - - // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<FastCallAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << "stdcall" << "fastcall"; - return; - } - - d->addAttr(::new (S.Context) StdCallAttr()); -} - -/// Diagnose the use of a non-standard calling convention on the given -/// function. -static void DiagnoseCConv(FunctionDecl *D, const char *CConv, - SourceLocation Loc, Sema &S) { - if (!D->hasPrototype()) { - S.Diag(Loc, diag::err_cconv_knr) << CConv; - return; - } - - const FunctionProtoType *T = D->getType()->getAs<FunctionProtoType>(); - if (T->isVariadic()) { - S.Diag(Loc, diag::err_cconv_varargs) << CConv; - return; - } + D->addAttr(::new (S.Context) SectionAttr(S.Context, SE->getString())); } -static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { - // Attribute has no 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; - } - - DiagnoseCConv(cast<FunctionDecl>(d), "fastcall", Attr.getLoc(), S); - - // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<StdCallAttr>()) { - S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) - << "fastcall" << "stdcall"; - return; - } - - d->addAttr(::new (S.Context) FastCallAttr()); -} static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { // check the attribute arguments. @@ -1349,7 +1257,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(), + d->addAttr(::new (S.Context) FormatAttr(S.Context, Format, Idx.getZExtValue(), FirstArg.getZExtValue())); } @@ -1435,7 +1343,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(ArgExpr->getLocStart(), diag::err_attribute_not_string) <<"annotate"; return; } - d->addAttr(::new (S.Context) AnnotateAttr(SE->getString())); + d->addAttr(::new (S.Context) AnnotateAttr(S.Context, SE->getString())); } static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1608,9 +1516,15 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (!IntegerMode) NewTy = S.Context.DoubleTy; else if (OldTy->isSignedIntegerType()) - NewTy = S.Context.LongLongTy; + if (S.Context.Target.getLongWidth() == 64) + NewTy = S.Context.LongTy; + else + NewTy = S.Context.LongLongTy; else - NewTy = S.Context.UnsignedLongLongTy; + if (S.Context.Target.getLongWidth() == 64) + NewTy = S.Context.UnsignedLongTy; + else + NewTy = S.Context.UnsignedLongLongTy; break; case 96: NewTy = S.Context.LongDoubleTy; @@ -1903,7 +1817,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_base_check: HandleBaseCheckAttr (D, Attr, S); break; case AttributeList::AT_carries_dependency: HandleDependencyAttr (D, Attr, S); break; - case AttributeList::AT_cdecl: HandleCDeclAttr (D, Attr, S); break; case AttributeList::AT_constructor: HandleConstructorAttr (D, Attr, S); break; case AttributeList::AT_deprecated: HandleDeprecatedAttr (D, Attr, S); break; case AttributeList::AT_destructor: HandleDestructorAttr (D, Attr, S); break; @@ -1912,7 +1825,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_ext_vector_type: HandleExtVectorTypeAttr(scope, D, Attr, S); break; - case AttributeList::AT_fastcall: HandleFastCallAttr (D, Attr, S); break; case AttributeList::AT_final: HandleFinalAttr (D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; @@ -1935,7 +1847,6 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; - case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; case AttributeList::AT_unavailable: HandleUnavailableAttr (D, Attr, S); break; case AttributeList::AT_unused: HandleUnusedAttr (D, Attr, S); break; case AttributeList::AT_used: HandleUsedAttr (D, Attr, S); break; @@ -1964,6 +1875,11 @@ static void ProcessDeclAttribute(Scope *scope, Decl *D, case AttributeList::AT_no_instrument_function: // Interacts with -pg. // Just ignore break; + case AttributeList::AT_stdcall: + case AttributeList::AT_cdecl: + case AttributeList::AT_fastcall: + // These are all treated as type attributes. + break; default: // Ask target about the attribute. const TargetAttributesSema &TargetAttrs = S.getTargetAttributesSema(); @@ -2008,7 +1924,7 @@ void Sema::DeclApplyPragmaWeak(Scope *S, NamedDecl *ND, WeakInfo &W) { if (W.getAlias()) { // clone decl, impersonate __attribute(weak,alias(...)) IdentifierInfo *NDId = ND->getIdentifier(); NamedDecl *NewD = DeclClonePragmaWeak(ND, W.getAlias()); - NewD->addAttr(::new (Context) AliasAttr(NDId->getName())); + NewD->addAttr(::new (Context) AliasAttr(Context, NDId->getName())); NewD->addAttr(::new (Context) WeakAttr()); WeakTopLevelDecl.push_back(NewD); // FIXME: "hideous" code from Sema::LazilyCreateBuiltin @@ -2062,48 +1978,71 @@ void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { /// on the warning stack. Action::ParsingDeclStackState Sema::PushParsingDeclaration() { ParsingDeclDepth++; - return (ParsingDeclStackState) DelayedDeprecationWarnings.size(); -} - -static bool isDeclDeprecated(Decl *D) { - do { - if (D->hasAttr<DeprecatedAttr>()) - return true; - } while ((D = cast_or_null<Decl>(D->getDeclContext()))); - return false; + return (ParsingDeclStackState) DelayedDiagnostics.size(); } void Sema::PopParsingDeclaration(ParsingDeclStackState S, DeclPtrTy Ctx) { assert(ParsingDeclDepth > 0 && "empty ParsingDeclaration stack"); ParsingDeclDepth--; - if (DelayedDeprecationWarnings.empty()) + if (DelayedDiagnostics.empty()) return; unsigned SavedIndex = (unsigned) S; - assert(SavedIndex <= DelayedDeprecationWarnings.size() && + assert(SavedIndex <= DelayedDiagnostics.size() && "saved index is out of bounds"); - if (Ctx && !isDeclDeprecated(Ctx.getAs<Decl>())) { - for (unsigned I = 0, E = DelayedDeprecationWarnings.size(); I != E; ++I) { - SourceLocation Loc = DelayedDeprecationWarnings[I].first; - NamedDecl *&ND = DelayedDeprecationWarnings[I].second; - if (ND) { - Diag(Loc, diag::warn_deprecated) << ND->getDeclName(); - - // Prevent this from triggering multiple times. - ND = 0; + // We only want to actually emit delayed diagnostics when we + // successfully parsed a decl. + Decl *D = Ctx ? Ctx.getAs<Decl>() : 0; + if (D) { + // We really do want to start with 0 here. We get one push for a + // decl spec and another for each declarator; in a decl group like: + // deprecated_typedef foo, *bar, baz(); + // only the declarator pops will be passed decls. This is correct; + // we really do need to consider delayed diagnostics from the decl spec + // for each of the different declarations. + for (unsigned I = 0, E = DelayedDiagnostics.size(); I != E; ++I) { + if (DelayedDiagnostics[I].Triggered) + continue; + + switch (DelayedDiagnostics[I].Kind) { + case DelayedDiagnostic::Deprecation: + HandleDelayedDeprecationCheck(DelayedDiagnostics[I], D); + break; + + case DelayedDiagnostic::Access: + HandleDelayedAccessCheck(DelayedDiagnostics[I], D); + break; } } } - DelayedDeprecationWarnings.set_size(SavedIndex); + DelayedDiagnostics.set_size(SavedIndex); +} + +static bool isDeclDeprecated(Decl *D) { + do { + if (D->hasAttr<DeprecatedAttr>()) + return true; + } while ((D = cast_or_null<Decl>(D->getDeclContext()))); + return false; +} + +void Sema::HandleDelayedDeprecationCheck(Sema::DelayedDiagnostic &DD, + Decl *Ctx) { + if (isDeclDeprecated(Ctx)) + return; + + DD.Triggered = true; + Diag(DD.Loc, diag::warn_deprecated) + << DD.DeprecationData.Decl->getDeclName(); } void Sema::EmitDeprecationWarning(NamedDecl *D, SourceLocation Loc) { // Delay if we're currently parsing a declaration. if (ParsingDeclDepth) { - DelayedDeprecationWarnings.push_back(std::make_pair(Loc, D)); + DelayedDiagnostics.push_back(DelayedDiagnostic::makeDeprecation(Loc, D)); return; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9ec95f3..9defcca 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -356,9 +356,7 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { } } - if (CheckEquivalentExceptionSpec( - Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), - New->getType()->getAs<FunctionProtoType>(), New->getLocation())) + if (CheckEquivalentExceptionSpec(Old, New)) Invalid = true; return Invalid; @@ -433,7 +431,7 @@ bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *, } else CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); - if (CurDecl) + if (CurDecl && CurDecl->getIdentifier()) return &II == CurDecl->getIdentifier(); else return false; @@ -486,7 +484,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, // If the base class is polymorphic or isn't empty, the new one is/isn't, too. RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl(); assert(BaseDecl && "Record type has no declaration"); - BaseDecl = BaseDecl->getDefinition(Context); + BaseDecl = BaseDecl->getDefinition(); assert(BaseDecl && "Base type is not incomplete, but has no definition"); CXXRecordDecl * CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl); assert(CXXBaseDecl && "Base type is not a C++ type"); @@ -641,7 +639,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, } // Attach the remaining base class specifiers to the derived class. - Class->setBases(Context, Bases, NumGoodBases); + Class->setBases(Bases, NumGoodBases); // Delete the remaining (good) base class specifiers, since their // data has been copied into the CXXRecordDecl. @@ -680,7 +678,8 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { CXXRecordDecl *DerivedRD = cast<CXXRecordDecl>(DerivedRT->getDecl()); CXXRecordDecl *BaseRD = cast<CXXRecordDecl>(BaseRT->getDecl()); - return DerivedRD->isDerivedFrom(BaseRD); + // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. + return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); } /// \brief Determine whether the type \p Derived is a C++ class that is @@ -712,7 +711,7 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { /// if there is an error. bool Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, - unsigned InaccessibleBaseID, + AccessDiagnosticsKind ADK, unsigned AmbigiousBaseConvID, SourceLocation Loc, SourceRange Range, DeclarationName Name) { @@ -728,11 +727,20 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, (void)DerivationOkay; if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { - if (InaccessibleBaseID == 0) + if (ADK == ADK_quiet) return false; + // Check that the base class can be accessed. - return CheckBaseClassAccess(Derived, Base, InaccessibleBaseID, Paths, Loc, - Name); + switch (CheckBaseClassAccess(Loc, /*IsBaseToDerived*/ false, + Base, Derived, Paths.front(), + /*force*/ false, + /*unprivileged*/ false, + ADK)) { + case AR_accessible: return false; + case AR_inaccessible: return true; + case AR_dependent: return false; + case AR_delayed: return false; + } } // We know that the derived-to-base conversion is ambiguous, and @@ -763,8 +771,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, SourceLocation Loc, SourceRange Range, bool IgnoreAccess) { return CheckDerivedToBaseConversion(Derived, Base, - IgnoreAccess ? 0 : - diag::err_conv_to_inaccessible_base, + IgnoreAccess ? ADK_quiet : ADK_normal, diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName()); } @@ -1195,10 +1202,6 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, SourceLocation IdLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. - ExprTemporaries.clear(); - // Diagnose value-uses of fields to initialize themselves, e.g. // foo(foo) // where foo is not also a parameter to the constructor. @@ -1220,65 +1223,80 @@ Sema::BuildMemberInitializer(FieldDecl *Member, Expr **Args, for (unsigned i = 0; i < NumArgs; i++) HasDependentArg |= Args[i]->isTypeDependent(); - CXXConstructorDecl *C = 0; QualType FieldType = Member->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - if (FieldType->isDependentType()) { - // Can't check init for dependent type. - } else if (FieldType->isRecordType()) { - // Member is a record (struct/union/class), so pass the initializer - // arguments down to the record's constructor. - if (!HasDependentArg) { - C = PerformInitializationByConstructor(FieldType, - MultiExprArg(*this, - (void**)Args, - NumArgs), - IdLoc, - SourceRange(IdLoc, RParenLoc), - Member->getDeclName(), - InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc), - ConstructorArgs); - - if (C) { - // Take over the constructor arguments as our own. - NumArgs = ConstructorArgs.size(); - Args = (Expr **)ConstructorArgs.take(); - } - } - } else if (NumArgs != 1 && NumArgs != 0) { - // The member type is not a record type (or an array of record - // types), so it can be only be default- or copy-initialized. - return Diag(IdLoc, diag::err_mem_initializer_mismatch) - << Member->getDeclName() << SourceRange(IdLoc, RParenLoc); - } else if (!HasDependentArg) { - Expr *NewExp; - if (NumArgs == 0) { - if (FieldType->isReferenceType()) { - Diag(IdLoc, diag::err_null_intialized_reference_member) - << Member->getDeclName(); - return Diag(Member->getLocation(), diag::note_declared_at); - } - NewExp = new (Context) CXXZeroInitValueExpr(FieldType, IdLoc, RParenLoc); - NumArgs = 1; - } - else - NewExp = (Expr*)Args[0]; - if (!Member->isInvalidDecl() && - PerformCopyInitialization(NewExp, FieldType, AA_Passing)) - return true; - Args[0] = NewExp; + if (FieldType->isDependentType() || HasDependentArg) { + // Can't check initialization for a member of dependent type or when + // any of the arguments are type-dependent expressions. + OwningExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + + // Erase any temporaries within this evaluation context; we're not + // going to track them in the AST, since we'll be rebuilding the + // ASTs during template instantiation. + ExprTemporaries.erase( + ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, + ExprTemporaries.end()); + + return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, + LParenLoc, + Init.takeAs<Expr>(), + RParenLoc); + } - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. - ExprTemporaries.clear(); + if (Member->isInvalidDecl()) + return true; + + // Initialize the member. + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(Member, 0); + InitializationKind Kind = + InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc); - // FIXME: Perform direct initialization of the member. + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + + OwningExprResult MemberInit = + InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, (void**)Args, NumArgs), 0); + if (MemberInit.isInvalid()) + return true; + + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + if (MemberInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the member + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + // Bump the reference count of all of the arguments. + for (unsigned I = 0; I != NumArgs; ++I) + Args[I]->Retain(); + + OwningExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, + LParenLoc, + Init.takeAs<Expr>(), + RParenLoc); + } + return new (Context) CXXBaseOrMemberInitializer(Context, Member, IdLoc, - C, LParenLoc, (Expr **)Args, - NumArgs, RParenLoc); + LParenLoc, + MemberInit.takeAs<Expr>(), + RParenLoc); } Sema::MemInitResult @@ -1291,76 +1309,118 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, HasDependentArg |= Args[i]->isTypeDependent(); SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getSourceRange().getBegin(); - if (!BaseType->isDependentType()) { - if (!BaseType->isRecordType()) - return Diag(BaseLoc, diag::err_base_init_does_not_name_class) - << BaseType << BaseTInfo->getTypeLoc().getSourceRange(); - - // 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 - // a direct non-virtual base class and an inherited virtual base - // class, the mem-initializer is ill-formed. - if (DirectBaseSpec && VirtualBaseSpec) - return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) - << BaseType << BaseTInfo->getTypeLoc().getSourceRange(); - // 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 << ClassDecl->getNameAsCString() - << BaseTInfo->getTypeLoc().getSourceRange(); - } - - CXXConstructorDecl *C = 0; - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - if (!BaseType->isDependentType() && !HasDependentArg) { - DeclarationName Name = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(BaseType).getUnqualifiedType()); - - C = PerformInitializationByConstructor(BaseType, - MultiExprArg(*this, - (void**)Args, NumArgs), - BaseLoc, - SourceRange(BaseLoc, RParenLoc), - Name, - InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc), - ConstructorArgs); - if (C) { - // Take over the constructor arguments as our own. - NumArgs = ConstructorArgs.size(); - Args = (Expr **)ConstructorArgs.take(); - } + if (BaseType->isDependentType() || HasDependentArg) { + // Can't check initialization for a base of dependent type or when + // any of the arguments are type-dependent expressions. + OwningExprResult BaseInit + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + + // Erase any temporaries within this evaluation context; we're not + // going to track them in the AST, since we'll be rebuilding the + // ASTs during template instantiation. + ExprTemporaries.erase( + ExprTemporaries.begin() + ExprEvalContexts.back().NumTemporaries, + ExprTemporaries.end()); + + return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, + LParenLoc, + BaseInit.takeAs<Expr>(), + RParenLoc); } + + if (!BaseType->isRecordType()) + return Diag(BaseLoc, diag::err_base_init_does_not_name_class) + << BaseType << BaseTInfo->getTypeLoc().getSourceRange(); - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. - ExprTemporaries.clear(); + // 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 + // a direct non-virtual base class and an inherited virtual base + // class, the mem-initializer is ill-formed. + if (DirectBaseSpec && VirtualBaseSpec) + return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) + << BaseType << BaseTInfo->getTypeLoc().getSourceRange(); + // 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 << ClassDecl->getNameAsCString() + << BaseTInfo->getTypeLoc().getSourceRange(); + + CXXBaseSpecifier *BaseSpec + = const_cast<CXXBaseSpecifier *>(DirectBaseSpec); + if (!BaseSpec) + BaseSpec = const_cast<CXXBaseSpecifier *>(VirtualBaseSpec); + + // Initialize the base. + InitializedEntity BaseEntity = + InitializedEntity::InitializeBase(Context, BaseSpec); + InitializationKind Kind = + InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc); + + InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); + + OwningExprResult BaseInit = + InitSeq.Perform(*this, BaseEntity, Kind, + MultiExprArg(*this, (void**)Args, NumArgs), 0); + if (BaseInit.isInvalid()) + return true; - return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, C, - LParenLoc, (Expr **)Args, - NumArgs, RParenLoc); + // C++0x [class.base.init]p7: + // The initialization of each base and member constitutes a + // full-expression. + BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit)); + if (BaseInit.isInvalid()) + return true; + + // If we are in a dependent context, template instantiation will + // perform this type-checking again. Just save the arguments that we + // received in a ParenListExpr. + // FIXME: This isn't quite ideal, since our ASTs don't capture all + // of the information that we have about the base + // initializer. However, deconstructing the ASTs is a dicey process, + // and this approach is far more likely to get the corner cases right. + if (CurContext->isDependentContext()) { + // Bump the reference count of all of the arguments. + for (unsigned I = 0; I != NumArgs; ++I) + Args[I]->Retain(); + + OwningExprResult Init + = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc)); + return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, + LParenLoc, + Init.takeAs<Expr>(), + RParenLoc); + } + + return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, + LParenLoc, + BaseInit.takeAs<Expr>(), + RParenLoc); } bool Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, - CXXBaseOrMemberInitializer **Initializers, - unsigned NumInitializers, - bool IsImplicitConstructor) { + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers, + bool IsImplicitConstructor, + bool AnyErrors) { // We need to build the initializer AST according to order of construction // and not what user specified in the Initializers list. CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Constructor->getDeclContext()); @@ -1403,6 +1463,8 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, AllToInit.push_back(Member); } } else { + llvm::SmallVector<CXXBaseSpecifier *, 4> BasesToDefaultInit; + // Push virtual bases before others. for (CXXRecordDecl::base_class_iterator VBase = ClassDecl->vbases_begin(), @@ -1412,44 +1474,34 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, if (CXXBaseOrMemberInitializer *Value = AllBaseFields.lookup(VBase->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); - } - else { - CXXRecordDecl *VBaseDecl = - cast<CXXRecordDecl>(VBase->getType()->getAs<RecordType>()->getDecl()); - assert(VBaseDecl && "SetBaseOrMemberInitializers - VBaseDecl null"); - CXXConstructorDecl *Ctor = VBaseDecl->getDefaultConstructor(Context); - if (!Ctor) { - Diag(Constructor->getLocation(), diag::err_missing_default_ctor) - << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) - << 0 << VBase->getType(); - Diag(VBaseDecl->getLocation(), diag::note_previous_decl) - << Context.getTagDeclType(VBaseDecl); + } else if (!AnyErrors) { + InitializedEntity InitEntity + = InitializedEntity::InitializeBase(Context, VBase); + InitializationKind InitKind + = InitializationKind::CreateDefault(Constructor->getLocation()); + InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); + OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind, + MultiExprArg(*this, 0, 0)); + BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit)); + if (BaseInit.isInvalid()) { HadError = true; continue; } - ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); - if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), - Constructor->getLocation(), CtorArgs)) + // Don't attach synthesized base initializers in a dependent + // context; they'll be checked again at template instantiation + // time. + if (CurContext->isDependentContext()) continue; - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); - - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if - // necessary. - // FIXME: Is there any better source-location information we can give? - ExprTemporaries.clear(); - CXXBaseOrMemberInitializer *Member = + CXXBaseOrMemberInitializer *CXXBaseInit = new (Context) CXXBaseOrMemberInitializer(Context, Context.getTrivialTypeSourceInfo(VBase->getType(), SourceLocation()), - Ctor, SourceLocation(), - CtorArgs.takeAs<Expr>(), - CtorArgs.size(), + BaseInit.takeAs<Expr>(), SourceLocation()); - AllToInit.push_back(Member); + AllToInit.push_back(CXXBaseInit); } } @@ -1466,43 +1518,34 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, = AllBaseFields.lookup(Base->getType()->getAs<RecordType>())) { AllToInit.push_back(Value); } - else { - CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); - assert(BaseDecl && "SetBaseOrMemberInitializers - BaseDecl null"); - CXXConstructorDecl *Ctor = BaseDecl->getDefaultConstructor(Context); - if (!Ctor) { - Diag(Constructor->getLocation(), diag::err_missing_default_ctor) - << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) - << 0 << Base->getType(); - Diag(BaseDecl->getLocation(), diag::note_previous_decl) - << Context.getTagDeclType(BaseDecl); + else if (!AnyErrors) { + InitializedEntity InitEntity + = InitializedEntity::InitializeBase(Context, Base); + InitializationKind InitKind + = InitializationKind::CreateDefault(Constructor->getLocation()); + InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); + OwningExprResult BaseInit = InitSeq.Perform(*this, InitEntity, InitKind, + MultiExprArg(*this, 0, 0)); + BaseInit = MaybeCreateCXXExprWithTemporaries(move(BaseInit)); + if (BaseInit.isInvalid()) { HadError = true; continue; } - - ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); - if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), - Constructor->getLocation(), CtorArgs)) + + // Don't attach synthesized base initializers in a dependent + // context; they'll be regenerated at template instantiation + // time. + if (CurContext->isDependentContext()) continue; - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); - - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if - // necessary. - // FIXME: Is there any better source-location information we can give? - ExprTemporaries.clear(); - CXXBaseOrMemberInitializer *Member = + CXXBaseOrMemberInitializer *CXXBaseInit = new (Context) CXXBaseOrMemberInitializer(Context, Context.getTrivialTypeSourceInfo(Base->getType(), SourceLocation()), - Ctor, SourceLocation(), - CtorArgs.takeAs<Expr>(), - CtorArgs.size(), + BaseInit.takeAs<Expr>(), SourceLocation()); - AllToInit.push_back(Member); + AllToInit.push_back(CXXBaseInit); } } } @@ -1535,66 +1578,49 @@ Sema::SetBaseOrMemberInitializers(CXXConstructorDecl *Constructor, continue; } - if ((*Field)->getType()->isDependentType()) + if ((*Field)->getType()->isDependentType() || AnyErrors) continue; QualType FT = Context.getBaseElementType((*Field)->getType()); - if (const RecordType* RT = FT->getAs<RecordType>()) { - CXXConstructorDecl *Ctor = - cast<CXXRecordDecl>(RT->getDecl())->getDefaultConstructor(Context); - if (!Ctor) { - Diag(Constructor->getLocation(), diag::err_missing_default_ctor) - << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) - << 1 << (*Field)->getDeclName(); - Diag(Field->getLocation(), diag::note_field_decl); - Diag(RT->getDecl()->getLocation(), diag::note_previous_decl) - << Context.getTagDeclType(RT->getDecl()); + if (FT->getAs<RecordType>()) { + InitializedEntity InitEntity + = InitializedEntity::InitializeMember(*Field); + InitializationKind InitKind + = InitializationKind::CreateDefault(Constructor->getLocation()); + + InitializationSequence InitSeq(*this, InitEntity, InitKind, 0, 0); + OwningExprResult MemberInit = InitSeq.Perform(*this, InitEntity, InitKind, + MultiExprArg(*this, 0, 0)); + MemberInit = MaybeCreateCXXExprWithTemporaries(move(MemberInit)); + if (MemberInit.isInvalid()) { HadError = true; continue; } - - if (FT.isConstQualified() && Ctor->isTrivial()) { - Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) - << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) - << 1 << (*Field)->getDeclName(); - Diag((*Field)->getLocation(), diag::note_declared_at); - HadError = true; - } - - // Don't create initializers for trivial constructors, since they don't - // actually need to be run. - if (Ctor->isTrivial()) - continue; - - ASTOwningVector<&ActionBase::DeleteExpr> CtorArgs(*this); - if (CompleteConstructorCall(Ctor, MultiExprArg(*this, 0, 0), - Constructor->getLocation(), CtorArgs)) + + // Don't attach synthesized member initializers in a dependent + // context; they'll be regenerated a template instantiation + // time. + if (CurContext->isDependentContext()) continue; - // FIXME: CXXBaseOrMemberInitializer should only contain a single - // subexpression so we can wrap it in a CXXExprWithTemporaries if necessary. - ExprTemporaries.clear(); CXXBaseOrMemberInitializer *Member = new (Context) CXXBaseOrMemberInitializer(Context, *Field, SourceLocation(), - Ctor, SourceLocation(), - CtorArgs.takeAs<Expr>(), - CtorArgs.size(), + MemberInit.takeAs<Expr>(), SourceLocation()); AllToInit.push_back(Member); - MarkDeclarationReferenced(Constructor->getLocation(), Ctor); } else if (FT->isReferenceType()) { - Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) + Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 0 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); HadError = true; } else if (FT.isConstQualified()) { - Diag(Constructor->getLocation(), diag::err_unintialized_member_in_ctor) + Diag(Constructor->getLocation(), diag::err_uninitialized_member_in_ctor) << (int)IsImplicitConstructor << Context.getTagDeclType(ClassDecl) << 1 << (*Field)->getDeclName(); Diag((*Field)->getLocation(), diag::note_declared_at); @@ -1659,7 +1685,8 @@ static void *GetKeyForMember(CXXBaseOrMemberInitializer *Member, /// ActOnMemInitializers - Handle the member initializers for a constructor. void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, SourceLocation ColonLoc, - MemInitTy **MemInits, unsigned NumMemInits) { + MemInitTy **MemInits, unsigned NumMemInits, + bool AnyErrors) { if (!ConstructorDecl) return; @@ -1709,7 +1736,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, SetBaseOrMemberInitializers(Constructor, reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), - NumMemInits, false); + NumMemInits, false, AnyErrors); if (Constructor->isDependentContext()) return; @@ -1860,7 +1887,7 @@ void Sema::ActOnDefaultCtorInitializers(DeclPtrTy CDtorDecl) { if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(CDtorDecl.getAs<Decl>())) - SetBaseOrMemberInitializers(Constructor, 0, 0, false); + SetBaseOrMemberInitializers(Constructor, 0, 0, false, false); } namespace { @@ -1978,13 +2005,15 @@ bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, if (!RT) return false; - const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); - if (!RD) - return false; + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); if (CurrentRD && CurrentRD != RD) return false; + // FIXME: is this reasonable? It matches current behavior, but.... + if (!RD->getDefinition()) + return false; + if (!RD->isAbstract()) return false; @@ -2086,6 +2115,11 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { if (Record->isInvalidDecl()) return; + // Set access bits correctly on the directly-declared conversions. + UnresolvedSetImpl *Convs = Record->getConversionFunctions(); + for (UnresolvedSetIterator I = Convs->begin(), E = Convs->end(); I != E; ++I) + Convs->setAccess(I, (*I)->getAccess()); + if (!Record->isAbstract()) { // Collect all the pure virtual methods and see if this is an abstract // class after all. @@ -2227,7 +2261,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, VarDecl::None, 0); - CopyConstructor->setParams(Context, &FromParam, 1); + CopyConstructor->setParams(&FromParam, 1); ClassDecl->addDecl(CopyConstructor); } @@ -2311,7 +2345,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*IdentifierInfo=*/0, ArgType, /*TInfo=*/0, VarDecl::None, 0); - CopyAssignment->setParams(Context, &FromParam, 1); + CopyAssignment->setParams(&FromParam, 1); // Don't call addedAssignmentOperator. There is no way to distinguish an // implicit from an explicit assignment operator. @@ -2793,13 +2827,16 @@ Sema::DeclPtrTy Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { Sema::DeclPtrTy Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation IdentLoc, IdentifierInfo *II, - SourceLocation LBrace) { + SourceLocation LBrace, + AttributeList *AttrList) { NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IdentLoc, II); Namespc->setLBracLoc(LBrace); Scope *DeclRegionScope = NamespcScope->getParent(); + ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); + if (II) { // C++ [namespace.def]p2: // The identifier in an original-namespace-definition shall not have been @@ -3654,7 +3691,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, (NestedNameSpecifier *)SS.getScopeRep(), IdentLoc, R.getFoundDecl()); - CurContext->addDecl(AliasDecl); + PushOnScopeChains(AliasDecl, S); return DeclPtrTy::make(AliasDecl); } @@ -3668,13 +3705,16 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, = cast<CXXRecordDecl>(Constructor->getDeclContext()); assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); - if (SetBaseOrMemberInitializers(Constructor, 0, 0, true)) { + DeclContext *PreviousContext = CurContext; + CurContext = Constructor; + if (SetBaseOrMemberInitializers(Constructor, 0, 0, true, false)) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl); Constructor->setInvalidDecl(); } else { Constructor->setUsed(); } + CurContext = PreviousContext; } void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, @@ -3683,6 +3723,10 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, "DefineImplicitDestructor - call it for implicit default dtor"); CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); + + DeclContext *PreviousContext = CurContext; + CurContext = Destructor; + // C++ [class.dtor] p5 // Before the implicitly-declared default destructor for a class is // implicitly defined, all the implicitly-declared default destructors @@ -3729,8 +3773,11 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, << CXXDestructor << Context.getTagDeclType(ClassDecl); Destructor->setInvalidDecl(); + CurContext = PreviousContext; + return; } + CurContext = PreviousContext; Destructor->setUsed(); } @@ -3745,6 +3792,9 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MethodDecl->getDeclContext()); + DeclContext *PreviousContext = CurContext; + CurContext = MethodDecl; + // C++[class.copy] p12 // Before the implicitly-declared copy assignment operator for a class is // implicitly defined, all implicitly-declared copy assignment operators @@ -3788,6 +3838,8 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, } if (!err) MethodDecl->setUsed(); + + CurContext = PreviousContext; } CXXMethodDecl * @@ -3808,7 +3860,7 @@ Sema::getAssignOperatorMethod(SourceLocation CurrentLocation, RHSType, CurrentLocation)); Expr *Args[2] = { &*LHS, &*RHS }; - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(CurrentLocation); AddMemberOperatorCandidates(clang::OO_Equal, SourceLocation(), Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; @@ -3830,6 +3882,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CopyConstructor->getDeclContext()); assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); + + DeclContext *PreviousContext = CurContext; + CurContext = CopyConstructor; + // C++ [class.copy] p209 // Before the implicitly-declared copy constructor for a class is // implicitly defined, all the implicitly-declared copy constructors @@ -3858,13 +3914,16 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, } } CopyConstructor->setUsed(); + + CurContext = PreviousContext; } Sema::OwningExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg ExprArgs, - bool RequiresZeroInit) { + bool RequiresZeroInit, + bool BaseInitialization) { bool Elidable = false; // C++ [class.copy]p15: @@ -3897,7 +3956,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, } return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, - Elidable, move(ExprArgs), RequiresZeroInit); + Elidable, move(ExprArgs), RequiresZeroInit, + BaseInitialization); } /// BuildCXXConstructExpr - Creates a complete call to a constructor, @@ -3906,32 +3966,17 @@ Sema::OwningExprResult Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg ExprArgs, - bool RequiresZeroInit) { + bool RequiresZeroInit, + bool BaseInitialization) { unsigned NumExprs = ExprArgs.size(); Expr **Exprs = (Expr **)ExprArgs.release(); MarkDeclarationReferenced(ConstructLoc, Constructor); return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc, Constructor, Elidable, Exprs, NumExprs, - RequiresZeroInit)); -} - -Sema::OwningExprResult -Sema::BuildCXXTemporaryObjectExpr(CXXConstructorDecl *Constructor, - QualType Ty, - SourceLocation TyBeginLoc, - MultiExprArg Args, - SourceLocation RParenLoc) { - unsigned NumExprs = Args.size(); - Expr **Exprs = (Expr **)Args.release(); - - MarkDeclarationReferenced(TyBeginLoc, Constructor); - return Owned(new (Context) CXXTemporaryObjectExpr(Context, Constructor, Ty, - TyBeginLoc, Exprs, - NumExprs, RParenLoc)); + RequiresZeroInit, BaseInitialization)); } - bool Sema::InitializeVarWithConstructor(VarDecl *VD, CXXConstructorDecl *Constructor, MultiExprArg Exprs) { @@ -3944,18 +3989,18 @@ bool Sema::InitializeVarWithConstructor(VarDecl *VD, Expr *Temp = TempResult.takeAs<Expr>(); MarkDeclarationReferenced(VD->getLocation(), Constructor); Temp = MaybeCreateCXXExprWithTemporaries(Temp); - VD->setInit(Context, Temp); + VD->setInit(Temp); return false; } -void Sema::FinalizeVarWithDestructor(VarDecl *VD, QualType DeclInitType) { - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>( - DeclInitType->getAs<RecordType>()->getDecl()); - if (!ClassDecl->hasTrivialDestructor()) - if (CXXDestructorDecl *Destructor = - const_cast<CXXDestructorDecl*>(ClassDecl->getDestructor(Context))) - MarkDeclarationReferenced(VD->getLocation(), Destructor); +void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); + if (!ClassDecl->hasTrivialDestructor()) { + CXXDestructorDecl *Destructor = ClassDecl->getDestructor(Context); + MarkDeclarationReferenced(VD->getLocation(), Destructor); + CheckDestructorAccess(VD->getLocation(), Record); + } } /// AddCXXDirectInitializerToDecl - This action is called immediately after @@ -3991,24 +4036,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, // exactly form was it (like the CodeGen) can handle both cases without // special case code. - // If either the declaration has a dependent type or if any of the expressions - // is type-dependent, we represent the initialization via a ParenListExpr for - // later use during template instantiation. - if (VDecl->getType()->isDependentType() || - Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) { - // Let clients know that initialization was done with a direct initializer. - VDecl->setCXXDirectInitializer(true); - - // Store the initialization expressions as a ParenListExpr. - unsigned NumExprs = Exprs.size(); - VDecl->setInit(Context, - new (Context) ParenListExpr(Context, LParenLoc, - (Expr **)Exprs.release(), - NumExprs, RParenLoc)); - return; - } - - // C++ 8.5p11: // The form of initialization (using parentheses or '=') is generally // insignificant, but does matter when the entity being initialized has a @@ -4017,7 +4044,8 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, if (const ArrayType *Array = Context.getAsArrayType(DeclInitType)) DeclInitType = Context.getBaseElementType(Array); - if (RequireCompleteType(VDecl->getLocation(), VDecl->getType(), + if (!VDecl->getType()->isDependentType() && + RequireCompleteType(VDecl->getLocation(), VDecl->getType(), diag::err_typecheck_decl_incomplete_type)) { VDecl->setInvalidDecl(); return; @@ -4029,14 +4057,30 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, AbstractVariableType)) VDecl->setInvalidDecl(); - const VarDecl *Def = 0; - if (VDecl->getDefinition(Def)) { + const VarDecl *Def; + if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) << VDecl->getDeclName(); Diag(Def->getLocation(), diag::note_previous_definition); VDecl->setInvalidDecl(); return; } + + // If either the declaration has a dependent type or if any of the + // expressions is type-dependent, we represent the initialization + // via a ParenListExpr for later use during template instantiation. + if (VDecl->getType()->isDependentType() || + Expr::hasAnyTypeDependentArguments((Expr **)Exprs.get(), Exprs.size())) { + // Let clients know that initialization was done with a direct initializer. + VDecl->setCXXDirectInitializer(true); + + // Store the initialization expressions as a ParenListExpr. + unsigned NumExprs = Exprs.size(); + VDecl->setInit(new (Context) ParenListExpr(Context, LParenLoc, + (Expr **)Exprs.release(), + NumExprs, RParenLoc)); + return; + } // Capture the variable that is being initialized and the style of // initialization. @@ -4056,11 +4100,11 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, } Result = MaybeCreateCXXExprWithTemporaries(move(Result)); - VDecl->setInit(Context, Result.takeAs<Expr>()); + VDecl->setInit(Result.takeAs<Expr>()); VDecl->setCXXDirectInitializer(true); - if (VDecl->getType()->getAs<RecordType>()) - FinalizeVarWithDestructor(VDecl, DeclInitType); + if (const RecordType *Record = VDecl->getType()->getAs<RecordType>()) + FinalizeVarWithDestructor(VDecl, Record); } /// \brief Add the applicable constructor candidates for an initialization @@ -4112,10 +4156,12 @@ static void AddConstructorInitializationCandidates(Sema &SemaRef, Constructor->isDefaultConstructor())) { if (ConstructorTmpl) SemaRef.AddTemplateOverloadCandidate(ConstructorTmpl, + ConstructorTmpl->getAccess(), /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); else - SemaRef.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + SemaRef.AddOverloadCandidate(Constructor, Constructor->getAccess(), + Args, NumArgs, CandidateSet); } } } @@ -4145,7 +4191,7 @@ Sema::TryInitializationByConstructor(QualType ClassType, SourceLocation Loc, InitializationKind Kind) { // Build the overload candidate set - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(Loc); AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, CandidateSet); @@ -4167,92 +4213,6 @@ Sema::TryInitializationByConstructor(QualType ClassType, return 0; } -/// \brief Perform initialization by constructor (C++ [dcl.init]p14), which -/// may occur as part of direct-initialization or copy-initialization. -/// -/// \param ClassType the type of the object being initialized, which must have -/// class type. -/// -/// \param ArgsPtr the arguments provided to initialize the object -/// -/// \param Loc the source location where the initialization occurs -/// -/// \param Range the source range that covers the entire initialization -/// -/// \param InitEntity the name of the entity being initialized, if known -/// -/// \param Kind the type of initialization being performed -/// -/// \param ConvertedArgs a vector that will be filled in with the -/// appropriately-converted arguments to the constructor (if initialization -/// succeeded). -/// -/// \returns the constructor used to initialize the object, if successful. -/// Otherwise, emits a diagnostic and returns NULL. -CXXConstructorDecl * -Sema::PerformInitializationByConstructor(QualType ClassType, - MultiExprArg ArgsPtr, - SourceLocation Loc, SourceRange Range, - DeclarationName InitEntity, - InitializationKind Kind, - ASTOwningVector<&ActionBase::DeleteExpr> &ConvertedArgs) { - - // Build the overload candidate set - Expr **Args = (Expr **)ArgsPtr.get(); - unsigned NumArgs = ArgsPtr.size(); - OverloadCandidateSet CandidateSet; - AddConstructorInitializationCandidates(*this, ClassType, Args, NumArgs, Kind, - CandidateSet); - - OverloadCandidateSet::iterator Best; - switch (BestViableFunction(CandidateSet, Loc, Best)) { - case OR_Success: - // We found a constructor. Break out so that we can convert the arguments - // appropriately. - break; - - case OR_No_Viable_Function: - if (InitEntity) - Diag(Loc, diag::err_ovl_no_viable_function_in_init) - << InitEntity << Range; - else - Diag(Loc, diag::err_ovl_no_viable_function_in_init) - << ClassType << Range; - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); - return 0; - - case OR_Ambiguous: - if (InitEntity) - Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range; - else - Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range; - PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, Args, NumArgs); - return 0; - - case OR_Deleted: - if (InitEntity) - Diag(Loc, diag::err_ovl_deleted_init) - << Best->Function->isDeleted() - << InitEntity << Range; - else { - const CXXRecordDecl *RD = - cast<CXXRecordDecl>(ClassType->getAs<RecordType>()->getDecl()); - Diag(Loc, diag::err_ovl_deleted_init) - << Best->Function->isDeleted() - << RD->getDeclName() << Range; - } - PrintOverloadCandidates(CandidateSet, OCD_AllCandidates, Args, NumArgs); - return 0; - } - - // Convert the arguments, fill in default arguments, etc. - CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); - if (CompleteConstructorCall(Constructor, move(ArgsPtr), Loc, ConvertedArgs)) - return 0; - - return Constructor; -} - /// \brief Given a constructor and the set of arguments provided for the /// constructor, convert the arguments and add any required default arguments /// to form a proper call to this constructor. @@ -4453,7 +4413,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; ICS->Standard.Third = ICK_Identity; ICS->Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS->Standard.ToTypePtr = T1.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; @@ -4486,7 +4448,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, CXXRecordDecl *T2RecordDecl = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(DeclLoc); const UnresolvedSetImpl *Conversions = T2RecordDecl->getVisibleConversionFunctions(); for (UnresolvedSetImpl::iterator I = Conversions->begin(), @@ -4509,10 +4471,11 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (Conv->getConversionType()->isLValueReferenceType() && (AllowExplicit || !Conv->isExplicit())) { if (ConvTemplate) - AddTemplateConversionCandidate(ConvTemplate, ActingDC, + AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), ActingDC, Init, DeclType, CandidateSet); else - AddConversionCandidate(Conv, ActingDC, Init, DeclType, CandidateSet); + AddConversionCandidate(Conv, I.getAccess(), ActingDC, Init, + DeclType, CandidateSet); } } @@ -4606,6 +4569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) { if (!ICS) Diag(DeclLoc, diag::err_not_reference_to_const_init) + << T1.isVolatileQualified() << T1 << int(InitLvalue != Expr::LV_Valid) << T2 << Init->getSourceRange(); return true; @@ -4642,7 +4606,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity; ICS->Standard.Third = ICK_Identity; ICS->Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS->Standard.ToTypePtr = T1.getAsOpaquePtr(); + ICS->Standard.setToType(0, T2); + ICS->Standard.setToType(1, T1); + ICS->Standard.setToType(2, T1); ICS->Standard.ReferenceBinding = true; ICS->Standard.DirectBinding = false; ICS->Standard.RRefBinding = isRValRef; @@ -5611,7 +5577,8 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, QualType NewTy = New->getType()->getAs<FunctionType>()->getResultType(); QualType OldTy = Old->getType()->getAs<FunctionType>()->getResultType(); - if (Context.hasSameType(NewTy, OldTy)) + if (Context.hasSameType(NewTy, OldTy) || + NewTy->isDependentType() || OldTy->isDependentType()) return false; // Check if the return types are covariant @@ -5665,8 +5632,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, } // Check if we the conversion from derived to base is valid. - if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, - diag::err_covariant_return_inaccessible_base, + if (CheckDerivedToBaseConversion(NewClassTy, OldClassTy, ADK_covariance, diag::err_covariant_return_ambiguous_derived_to_base_conv, // FIXME: Should this point to the return type? New->getLocation(), SourceRange(), New->getDeclName())) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 1b07d19..1e9b56a 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -446,18 +446,19 @@ Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, // Category ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); assert (CatDecl && "MatchOneProtocolPropertiesInClass"); - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Pr = (*P); - ObjCCategoryDecl::prop_iterator CP, CE; - // Is this property already in category's list of properties? - for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP) - if ((*CP)->getIdentifier() == Pr->getIdentifier()) - break; - if (CP != CE) - // Property protocol already exist in class. Diagnose any mismatch. - DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); - } + if (!CatDecl->IsClassExtension()) + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Pr = (*P); + ObjCCategoryDecl::prop_iterator CP, CE; + // Is this property already in category's list of properties? + for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP) + if ((*CP)->getIdentifier() == Pr->getIdentifier()) + break; + if (CP != CE) + // Property protocol already exist in class. Diagnose any mismatch. + DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); + } return; } for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), @@ -596,44 +597,59 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc) { - ObjCCategoryDecl *CDecl = - ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc, - CategoryLoc, CategoryName); - // FIXME: PushOnScopeChains? - CurContext->addDecl(CDecl); - + ObjCCategoryDecl *CDecl = 0; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc); - /// Check that class of this category is already completely declared. - if (!IDecl || IDecl->isForwardDecl()) { - CDecl->setInvalidDecl(); - Diag(ClassLoc, diag::err_undef_interface) << ClassName; - return DeclPtrTy::make(CDecl); - } + if (!CategoryName) { + // Class extensions require a special treatment. Use an existing one. + for (CDecl = IDecl->getCategoryList(); CDecl; + CDecl = CDecl->getNextClassCategory()) + if (CDecl->IsClassExtension()) + break; + } + if (!CDecl) { + CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, ClassLoc, + CategoryLoc, CategoryName); + // FIXME: PushOnScopeChains? + CurContext->addDecl(CDecl); + + /// Check that class of this category is already completely declared. + if (!IDecl || IDecl->isForwardDecl()) { + CDecl->setInvalidDecl(); + Diag(ClassLoc, diag::err_undef_interface) << ClassName; + return DeclPtrTy::make(CDecl); + } - CDecl->setClassInterface(IDecl); + CDecl->setClassInterface(IDecl); + // Insert first use of 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); - /// Check for duplicate interface declaration for this category - ObjCCategoryDecl *CDeclChain; - for (CDeclChain = IDecl->getCategoryList(); CDeclChain; - CDeclChain = CDeclChain->getNextClassCategory()) { - if (CategoryName && CDeclChain->getIdentifier() == CategoryName) { - Diag(CategoryLoc, diag::warn_dup_category_def) - << ClassName << CategoryName; - Diag(CDeclChain->getLocation(), diag::note_previous_definition); - break; + if (CategoryName) { + /// Check for duplicate interface declaration for this category + ObjCCategoryDecl *CDeclChain; + for (CDeclChain = IDecl->getCategoryList(); CDeclChain; + CDeclChain = CDeclChain->getNextClassCategory()) { + if (CDeclChain->getIdentifier() == CategoryName) { + // Class extensions can be declared multiple times. + Diag(CategoryLoc, diag::warn_dup_category_def) + << ClassName << CategoryName; + Diag(CDeclChain->getLocation(), diag::note_previous_definition); + break; + } } + if (!CDeclChain) + CDecl->insertNextClassCategory(); } - if (!CDeclChain) - CDecl->insertNextClassCategory(); if (NumProtoRefs) { CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, ProtoLocs, Context); // Protocols in the class extension belong to the class. - if (!CDecl->getIdentifier()) + if (CDecl->IsClassExtension()) IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, ProtoLocs, Context); @@ -1102,11 +1118,12 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, CollectImmediateProperties((*PI), PropMap); } if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { - for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), - E = CATDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = (*P); - PropMap[Prop->getIdentifier()] = Prop; - } + if (!CATDecl->IsClassExtension()) + for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), + E = CATDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + PropMap[Prop->getIdentifier()] = Prop; + } // scan through class's protocols. for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), E = CATDecl->protocol_end(); PI != E; ++PI) @@ -1127,6 +1144,46 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, } } +/// LookupPropertyDecl - Looks up a property in the current class and all +/// its protocols. +ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, + IdentifierInfo *II) { + if (const ObjCInterfaceDecl *IDecl = + dyn_cast<ObjCInterfaceDecl>(CDecl)) { + for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), + E = IDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through class's protocols. + for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), + E = IDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + else if (const ObjCProtocolDecl *PDecl = + dyn_cast<ObjCProtocolDecl>(CDecl)) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { + ObjCPropertyDecl *Prop = (*P); + if (Prop->getIdentifier() == II) + return Prop; + } + // scan through protocol's protocols. + for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), + E = PDecl->protocol_end(); PI != E; ++PI) { + ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); + if (Prop) + return Prop; + } + } + return 0; +} + + void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, ObjCContainerDecl *CDecl, const llvm::DenseSet<Selector>& InsMap) { @@ -1149,7 +1206,14 @@ void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || PropImplMap.count(Prop)) continue; - + if (LangOpts.ObjCNonFragileABI2) { + ActOnPropertyImplDecl(IMPDecl->getLocation(), + SourceLocation(), + true, DeclPtrTy::make(IMPDecl), + Prop->getIdentifier(), + Prop->getIdentifier()); + continue; + } if (!InsMap.count(Prop->getGetterName())) { Diag(Prop->getLocation(), isa<ObjCCategoryDecl>(CDecl) ? @@ -1214,7 +1278,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, // Check class extensions (unnamed categories) for (ObjCCategoryDecl *Categories = I->getCategoryList(); Categories; Categories = Categories->getNextClassCategory()) { - if (!Categories->getIdentifier()) { + if (Categories->IsClassExtension()) { ImplMethodsVsClassMethods(IMPDecl, Categories, IncompleteImpl); break; } @@ -1222,7 +1286,7 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { // For extended class, unimplemented methods in its protocols will // be reported in the primary class. - if (C->getIdentifier()) { + if (!C->IsClassExtension()) { for (ObjCCategoryDecl::protocol_iterator PI = C->protocol_begin(), E = C->protocol_end(); PI != E; ++PI) CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl, @@ -1443,7 +1507,8 @@ void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) { // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - Entry.Next = new ObjCMethodList(Method, Entry.Next); + ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>(); + Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next); } // FIXME: Finish implementing -Wno-strict-selector-match. @@ -1506,7 +1571,8 @@ void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) { if (!match) { // We have a new signature for an existing method - add it. // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". - struct ObjCMethodList *OMI = new ObjCMethodList(Method, FirstMethod.Next); + ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>(); + ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next); FirstMethod.Next = OMI; } } @@ -1777,17 +1843,18 @@ void Sema::ActOnAtEnd(SourceRange AtEnd, // Compare protocol properties with those in category CompareProperties(C, DeclPtrTy::make(C)); - if (C->getIdentifier() == 0) + if (C->IsClassExtension()) DiagnoseClassExtensionDupMethods(C, C->getClassInterface()); } if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) { - // ProcessPropertyDecl is responsible for diagnosing conflicts with any - // user-defined setter/getter. It also synthesizes setter/getter methods - // and adds them to the DeclContext and global method pools. - for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), - E = CDecl->prop_end(); - I != E; ++I) - ProcessPropertyDecl(*I, CDecl); + if (CDecl->getIdentifier()) + // ProcessPropertyDecl is responsible for diagnosing conflicts with any + // user-defined setter/getter. It also synthesizes setter/getter methods + // and adds them to the DeclContext and global method pools. + for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), + E = CDecl->prop_end(); + I != E; ++I) + ProcessPropertyDecl(*I, CDecl); CDecl->setAtEndRange(AtEnd); } if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { @@ -2088,7 +2155,22 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // May modify Attributes. CheckObjCPropertyAttributes(T, AtLoc, Attributes); if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) - if (!CDecl->getIdentifier()) { + if (CDecl->IsClassExtension()) { + // Diagnose if this property is already in continuation class. + DeclContext *DC = dyn_cast<DeclContext>(ClassDecl); + assert(DC && "ClassDecl is not a DeclContext"); + DeclContext::lookup_result Found = DC->lookup(FD.D.getIdentifier()); + if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) { + Diag(AtLoc, diag::err_duplicate_property); + Diag((*Found.first)->getLocation(), diag::note_property_declare); + return DeclPtrTy(); + } + ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, + FD.D.getIdentifierLoc(), + FD.D.getIdentifier(), + AtLoc, T); + DC->addDecl(PDecl); + // This is a continuation class. property requires special // handling. if ((CCPrimary = CDecl->getClassInterface())) { @@ -2152,6 +2234,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, ProcessPropertyDecl(PIDecl, CCPrimary); return DeclPtrTy(); } + // No matching property found in the primary class. Just fall thru // and add property to continuation class's primary class. ClassDecl = CCPrimary; @@ -2246,6 +2329,28 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, return DeclPtrTy::make(PDecl); } +ObjCIvarDecl* +Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl, + IdentifierInfo *NameII) { + ObjCIvarDecl *Ivar = 0; + ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII); + if (Prop && !Prop->isInvalidDecl()) { + DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl); + QualType PropType = Context.getCanonicalType(Prop->getType()); + assert(EnclosingContext && + "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar"); + Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, + Prop->getLocation(), + NameII, PropType, /*Dinfo=*/0, + ObjCIvarDecl::Public, + (Expr *)0); + Ivar->setLexicalDeclContext(IDecl); + IDecl->addDecl(Ivar); + Prop->setPropertyIvarDecl(Ivar); + } + return Ivar; +} + /// ActOnPropertyImplDecl - This routine performs semantic checks and /// builds the AST node for a property implementation declaration; declared /// as @synthesize or @dynamic. @@ -2283,7 +2388,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, } if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { - if (CD->getIdentifier()) { + if (!CD->IsClassExtension()) { Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); Diag(property->getLocation(), diag::note_property_declare); return DeclPtrTy(); diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index 7e2a98d..9be411b 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -12,10 +12,11 @@ //===----------------------------------------------------------------------===// #include "Sema.h" -#include "clang/Basic/Diagnostic.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallPtrSet.h" namespace clang { @@ -92,6 +93,52 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { return FnT->hasExceptionSpec(); } +bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { + bool MissingEmptyExceptionSpecification = false; + if (!CheckEquivalentExceptionSpec(diag::err_mismatched_exception_spec, + diag::note_previous_declaration, + Old->getType()->getAs<FunctionProtoType>(), + Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), + New->getLocation(), + &MissingEmptyExceptionSpecification)) + return false; + + // The failure was something other than an empty exception + // specification; return an error. + if (!MissingEmptyExceptionSpecification) + return true; + + // The new function declaration is only missing an empty exception + // specification "throw()". If the throw() specification came from a + // function in a system header that has C linkage, just add an empty + // exception specification to the "new" declaration. This is an + // egregious workaround for glibc, which adds throw() specifications + // to many libc functions as an optimization. Unfortunately, that + // optimization isn't permitted by the C++ standard, so we're forced + // to work around it here. + if (isa<FunctionProtoType>(New->getType()) && + Context.getSourceManager().isInSystemHeader(Old->getLocation()) && + Old->isExternC()) { + const FunctionProtoType *NewProto + = cast<FunctionProtoType>(New->getType()); + QualType NewType = Context.getFunctionType(NewProto->getResultType(), + NewProto->arg_type_begin(), + NewProto->getNumArgs(), + NewProto->isVariadic(), + NewProto->getTypeQuals(), + true, false, 0, 0, + NewProto->getNoReturnAttr(), + NewProto->getCallConv()); + New->setType(NewType); + return false; + } + + Diag(New->getLocation(), diag::err_mismatched_exception_spec); + Diag(Old->getLocation(), diag::note_previous_declaration); + return true; +} + /// CheckEquivalentExceptionSpec - Check if the two types have equivalent /// exception specifications. Exception specifications are equivalent if /// they allow exactly the same set of exception types. It does not matter how @@ -111,12 +158,26 @@ bool Sema::CheckEquivalentExceptionSpec( bool Sema::CheckEquivalentExceptionSpec( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc) { + const FunctionProtoType *New, SourceLocation NewLoc, + bool *MissingEmptyExceptionSpecification) { + if (MissingEmptyExceptionSpecification) + *MissingEmptyExceptionSpecification = false; + bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); if (OldAny && NewAny) return false; if (OldAny || NewAny) { + if (MissingEmptyExceptionSpecification && Old->hasExceptionSpec() && + !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0 && + !New->hasExceptionSpec()) { + // The old type has a throw() exception specification and the + // new type has no exception specification, and the caller asked + // to handle this itself. + *MissingEmptyExceptionSpecification = true; + return true; + } + Diag(NewLoc, DiagID); if (NoteID.getDiagID() != 0) Diag(OldLoc, NoteID); @@ -232,8 +293,22 @@ bool Sema::CheckExceptionSpecSubset( if (Paths.isAmbiguous(CanonicalSuperT)) continue; - if (FindInaccessibleBase(CanonicalSubT, CanonicalSuperT, Paths, true)) - continue; + // Do this check from a context without privileges. + switch (CheckBaseClassAccess(SourceLocation(), false, + CanonicalSuperT, CanonicalSubT, + Paths.front(), + /*ForceCheck*/ true, + /*ForceUnprivileged*/ true, + ADK_quiet)) { + case AR_accessible: break; + case AR_inaccessible: continue; + case AR_dependent: + llvm_unreachable("access check dependent for unprivileged context"); + break; + case AR_delayed: + llvm_unreachable("access check delayed in non-declaration"); + break; + } Contained = true; break; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 50976f7..633884f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -14,7 +14,7 @@ #include "Sema.h" #include "SemaInit.h" #include "Lookup.h" -#include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/Analysis/AnalysisContext.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -200,6 +200,28 @@ void Sema::DefaultFunctionArrayConversion(Expr *&E) { } } +void Sema::DefaultFunctionArrayLvalueConversion(Expr *&E) { + DefaultFunctionArrayConversion(E); + + QualType Ty = E->getType(); + assert(!Ty.isNull() && "DefaultFunctionArrayLvalueConversion - missing type"); + if (!Ty->isDependentType() && Ty.hasQualifiers() && + (!getLangOptions().CPlusPlus || !Ty->isRecordType()) && + E->isLvalue(Context) == Expr::LV_Valid) { + // C++ [conv.lval]p1: + // [...] If T is a non-class type, the type of the rvalue is the + // cv-unqualified version of T. Otherwise, the type of the + // rvalue is T + // + // C99 6.3.2.1p2: + // If the lvalue has qualified type, the value has the unqualified + // version of the type of the lvalue; otherwise, the value has the + // type of the lvalue. + ImpCastExprToType(E, Ty.getUnqualifiedType(), CastExpr::CK_NoOp); + } +} + + /// UsualUnaryConversions - Performs various conversions that are common to most /// operators (C99 6.3). The conversions of array and function types are /// sometimes surpressed. For example, the array->pointer conversion doesn't @@ -233,7 +255,7 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) { return Expr; } - DefaultFunctionArrayConversion(Expr); + DefaultFunctionArrayLvalueConversion(Expr); return Expr; } @@ -678,7 +700,13 @@ static void DecomposeTemplateName(LookupResult &R, const UnqualifiedId &Id) { 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. static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) { + if (!Record->hasDefinition()) + return false; + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { CanQualType BaseT = SemaRef.Context.getCanonicalType((*I).getType()); @@ -686,7 +714,7 @@ static bool IsFullyFormedScope(Sema &SemaRef, CXXRecordDecl *Record) { if (!BaseRT) return false; CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(BaseRT->getDecl()); - if (!BaseRecord->isDefinition() || + if (!BaseRecord->hasDefinition() || !IsFullyFormedScope(SemaRef, BaseRecord)) return false; } @@ -719,7 +747,7 @@ static bool IsProvablyNotDerivedFrom(Sema &SemaRef, if (Bases.count(Record->getCanonicalDecl())) return false; - RecordDecl *RD = Record->getDefinition(SemaRef.Context); + RecordDecl *RD = Record->getDefinition(); if (!RD) return false; Record = cast<CXXRecordDecl>(RD); @@ -1243,9 +1271,9 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, else LookForIvars = (Lookup.isSingleResult() && Lookup.getFoundDecl()->isDefinedOutsideFunctionOrMethod()); - + ObjCInterfaceDecl *IFace = 0; if (LookForIvars) { - ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); + IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { // Diagnose using an ivar in a class method. @@ -1314,6 +1342,11 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S, } } } + if (LangOpts.ObjCNonFragileABI2 && LookForIvars && Lookup.empty()) { + ObjCIvarDecl *Ivar = SynthesizeNewPropertyIvar(IFace, II); + if (Ivar) + return LookupInObjCMethod(Lookup, S, II, AllowBuiltinCreation); + } // Sentinel value saying that we didn't do anything special. return Owned((Expr*) 0); } @@ -1487,7 +1520,7 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, bool NeedsADL) { // If this is a single, fully-resolved result and we don't need ADL, // just build an ordinary singleton decl ref. - if (!NeedsADL && R.isSingleResult()) + if (!NeedsADL && R.isSingleResult() && !R.getAsSingle<FunctionTemplateDecl>()) return BuildDeclarationNameExpr(SS, R.getNameLoc(), R.getFoundDecl()); // We only need to check the declaration if there's exactly one @@ -1497,16 +1530,20 @@ Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, CheckDeclInExpr(*this, R.getNameLoc(), R.getFoundDecl())) return ExprError(); + // Otherwise, just build an unresolved lookup expression. Suppress + // any lookup-related diagnostics; we'll hash these out later, when + // we've picked a target. + R.suppressDiagnostics(); + bool Dependent = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), 0); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, Dependent, + = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(), (NestedNameSpecifier*) SS.getScopeRep(), SS.getRange(), R.getLookupName(), R.getNameLoc(), NeedsADL, R.isOverloadedResult()); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - ULE->addDecl(*I); + ULE->addDecls(R.begin(), R.end()); return Owned(ULE); } @@ -1616,8 +1653,7 @@ Sema::OwningExprResult Sema::ActOnPredefinedExpr(SourceLocation Loc, if (cast<DeclContext>(currentDecl)->isDependentContext()) { ResTy = Context.DependentTy; } else { - unsigned Length = - PredefinedExpr::ComputeName(Context, IT, currentDecl).length(); + unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); ResTy = Context.CharTy.withConst(); @@ -1642,6 +1678,8 @@ Sema::OwningExprResult Sema::ActOnCharacterConstant(const Token &Tok) { Ty = Context.IntTy; // 'x' and L'x' -> int in C. else if (Literal.isWide()) Ty = Context.WCharTy; // L'x' -> wchar_t in C++. + else if (Literal.isMultiChar()) + Ty = Context.IntTy; // 'wxyz' -> int in C++. else Ty = Context.CharTy; // 'x' -> char in C++ @@ -2029,8 +2067,9 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, Expr *RHSExp = static_cast<Expr*>(Idx.get()); // Perform default conversions. - DefaultFunctionArrayConversion(LHSExp); - DefaultFunctionArrayConversion(RHSExp); + if (!LHSExp->getType()->getAs<VectorType>()) + DefaultFunctionArrayLvalueConversion(LHSExp); + DefaultFunctionArrayLvalueConversion(RHSExp); QualType LHSTy = LHSExp->getType(), RHSTy = RHSExp->getType(); @@ -2072,7 +2111,7 @@ Sema::CreateBuiltinArraySubscriptExpr(ExprArg Base, SourceLocation LLoc, ResultType = VTy->getElementType(); } else if (LHSTy->isArrayType()) { // If we see an array that wasn't promoted by - // DefaultFunctionArrayConversion, it must be an array that + // DefaultFunctionArrayLvalueConversion, it must be an array that // wasn't promoted because of the C90 rule that doesn't // allow promoting non-lvalue arrays. Warn, then // force the promotion here. @@ -2542,7 +2581,11 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, bool Dependent = BaseExprType->isDependentType() || R.isUnresolvableResult() || - UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs); + OverloadExpr::ComputeDependence(R.begin(), R.end(), TemplateArgs); + + // Suppress any lookup-related diagnostics; we'll do these when we + // pick a member. + R.suppressDiagnostics(); UnresolvedMemberExpr *MemExpr = UnresolvedMemberExpr::Create(Context, Dependent, @@ -2552,8 +2595,7 @@ Sema::BuildMemberReferenceExpr(ExprArg Base, QualType BaseExprType, Qualifier, SS.getRange(), MemberName, MemberLoc, TemplateArgs); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - MemExpr->addDecl(*I); + MemExpr->addDecls(R.begin(), R.end()); return Owned(MemExpr); } @@ -3001,7 +3043,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, if (DiagnoseUseOfDecl(OMD, MemberLoc)) return ExprError(); - return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel, + return Owned(new (Context) ObjCMessageExpr(Context, BaseExpr, Sel, OMD->getResultType(), OMD, OpLoc, MemberLoc, NULL, 0)); @@ -3248,7 +3290,8 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); // Instantiate the expression. - MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD); + MultiLevelTemplateArgumentList ArgList + = getTemplateInstantiationArgs(FD, 0, /*RelativeToPrimary=*/true); InstantiatingTemplate Inst(*this, CallLoc, Param, ArgList.getInnermost().getFlatArgumentList(), @@ -3770,7 +3813,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr, return CXXCheckCStyleCast(TyR, castType, castExpr, Kind, FunctionalStyle, ConversionDecl); - DefaultFunctionArrayConversion(castExpr); + DefaultFunctionArrayLvalueConversion(castExpr); // C99 6.5.4p2: the cast type needs to be void or scalar and the expression // type needs to be scalar. @@ -4807,7 +4850,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // // Suppress this for references: C++ 8.5.3p5. if (!lhsType->isReferenceType()) - DefaultFunctionArrayConversion(rExpr); + DefaultFunctionArrayLvalueConversion(rExpr); Sema::AssignConvertType result = CheckAssignmentConstraints(lhsType, rExpr->getType()); @@ -5690,6 +5733,9 @@ static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { case Expr::MLV_SubObjCPropertySetting: Diag = diag::error_no_subobject_property_setting; break; + case Expr::MLV_SubObjCPropertyGetterSetting: + Diag = diag::error_no_subobject_property_getter_setting; + break; } SourceRange Assign; @@ -5770,7 +5816,9 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, // C99 6.5.17 QualType Sema::CheckCommaOperands(Expr *LHS, Expr *&RHS, SourceLocation Loc) { // Comma performs lvalue conversion (C99 6.3.2.1), but not unary conversions. - DefaultFunctionArrayConversion(RHS); + // C++ does not perform this conversion (C++ [expr.comma]p1). + if (!getLangOptions().CPlusPlus) + DefaultFunctionArrayLvalueConversion(RHS); // FIXME: Check that RHS type is complete in C mode (it's legal for it to be // incomplete in C++). @@ -5961,8 +6009,7 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) { Diag(OpLoc, diag::err_typecheck_address_of) << "bit-field" << op->getSourceRange(); return QualType(); - } else if (isa<ExtVectorElementExpr>(op) || (isa<ArraySubscriptExpr>(op) && - cast<ArraySubscriptExpr>(op)->getBase()->getType()->isVectorType())){ + } else if (op->refersToVectorElement()) { // The operand cannot be an element of a vector Diag(OpLoc, diag::err_typecheck_address_of) << "vector element" << op->getSourceRange(); @@ -6337,17 +6384,11 @@ Action::OwningExprResult Sema::BuildBinOp(Scope *S, SourceLocation OpLoc, // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of // the arguments. - FunctionSet Functions; + UnresolvedSet<16> Functions; OverloadedOperatorKind OverOp = BinaryOperator::getOverloadedOperator(Opc); - if (OverOp != OO_None) { - if (S) - LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(), - Functions); - Expr *Args[2] = { lhs, rhs }; - DeclarationName OpName - = Context.DeclarationNames.getCXXOperatorName(OverOp); - ArgumentDependentLookup(OpName, /*Operator*/true, Args, 2, Functions); - } + if (S && OverOp != OO_None) + LookupOverloadedOperatorName(OverOp, S, lhs->getType(), rhs->getType(), + Functions); // Build the (potentially-overloaded, potentially-dependent) // binary operation. @@ -6383,7 +6424,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, resultType = CheckAddressOfOperand(Input, OpLoc); break; case UnaryOperator::Deref: - DefaultFunctionArrayConversion(Input); + DefaultFunctionArrayLvalueConversion(Input); resultType = CheckIndirectionOperand(Input, OpLoc); break; case UnaryOperator::Plus: @@ -6420,7 +6461,7 @@ Action::OwningExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, break; case UnaryOperator::LNot: // logical negation // Unlike +/-/~, integer promotions aren't done here (C99 6.5.3.3p5). - DefaultFunctionArrayConversion(Input); + DefaultFunctionArrayLvalueConversion(Input); resultType = Input->getType(); if (resultType->isDependentType()) break; @@ -6456,16 +6497,11 @@ Action::OwningExprResult Sema::BuildUnaryOp(Scope *S, SourceLocation OpLoc, // point. We perform both an operator-name lookup from the local // scope and an argument-dependent lookup based on the types of // the arguments. - FunctionSet Functions; + UnresolvedSet<16> Functions; OverloadedOperatorKind OverOp = UnaryOperator::getOverloadedOperator(Opc); - if (OverOp != OO_None) { - if (S) - LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), - Functions); - DeclarationName OpName - = Context.DeclarationNames.getCXXOperatorName(OverOp); - ArgumentDependentLookup(OpName, /*Operator*/true, &Input, 1, Functions); - } + if (S && OverOp != OO_None) + LookupOverloadedOperatorName(OverOp, S, Input->getType(), QualType(), + Functions); return CreateOverloadedUnaryOp(OpLoc, Opc, Functions, move(input)); } @@ -6595,7 +6631,7 @@ Sema::OwningExprResult Sema::ActOnBuiltinOffsetOf(Scope *S, // Promote the array so it looks more like a normal array subscript // expression. - DefaultFunctionArrayConversion(Res); + DefaultFunctionArrayLvalueConversion(Res); // C99 6.5.2.1p1 Expr *Idx = static_cast<Expr*>(OC.U.E); @@ -6772,6 +6808,8 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy; return; } + + CurBlock->ReturnType = RetTy; return; } @@ -6792,11 +6830,18 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // 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) - CurBlock->Params.push_back(FTI.ArgInfo[i].Param.getAs<ParmVarDecl>()); + for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { + ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); + if (Param->getIdentifier() == 0 && + !Param->isImplicit() && + !Param->isInvalidDecl() && + !getLangOptions().CPlusPlus) + Diag(Param->getLocation(), diag::err_parameter_name_omitted); + CurBlock->Params.push_back(Param); + } CurBlock->isVariadic = FTI.isVariadic; } - CurBlock->TheDecl->setParams(Context, CurBlock->Params.data(), + CurBlock->TheDecl->setParams(CurBlock->Params.data(), CurBlock->Params.size()); CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic); ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo); @@ -7255,6 +7300,7 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { // FIXME: keep track of references to static functions Function->setUsed(true); + return; } @@ -7390,7 +7436,7 @@ bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { DiagnoseAssignmentAsCondition(E); if (!E->isTypeDependent()) { - DefaultFunctionArrayConversion(E); + DefaultFunctionArrayLvalueConversion(E); QualType T = E->getType(); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index b004fc3..9eeda54 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -72,18 +72,17 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, if (const RecordType *RecordT = T->getAs<RecordType>()) { CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl()); // C++ [expr.typeid]p3: + // [...] If the type of the expression is a class type, the class + // shall be completely-defined. + if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid)) + return ExprError(); + + // C++ [expr.typeid]p3: // When typeid is applied to an expression other than an lvalue of a // polymorphic class type [...] [the] expression is an unevaluated // operand. [...] if (RecordD->isPolymorphic() && E->isLvalue(Context) == Expr::LV_Valid) isUnevaluatedOperand = false; - else { - // C++ [expr.typeid]p3: - // [...] If the type of the expression is a class type, the class - // shall be completely-defined. - if (RequireCompleteType(OpLoc, T, diag::err_incomplete_typeid)) - return ExprError(); - } } // C++ [expr.typeid]p4: @@ -195,7 +194,9 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, MultiExprArg exprs, SourceLocation *CommaLocs, SourceLocation RParenLoc) { - assert(TypeRep && "Missing type!"); + if (!TypeRep) + return ExprError(); + TypeSourceInfo *TInfo; QualType Ty = GetTypeFromParser(TypeRep, &TInfo); if (!TInfo) @@ -263,29 +264,18 @@ Sema::ActOnCXXTypeConstructExpr(SourceRange TypeRange, TypeTy *TypeRep, if (NumExprs > 1 || !Record->hasTrivialConstructor() || !Record->hasTrivialDestructor()) { - ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); - - CXXConstructorDecl *Constructor - = PerformInitializationByConstructor(Ty, move(exprs), - TypeRange.getBegin(), - SourceRange(TypeRange.getBegin(), - RParenLoc), - DeclarationName(), - InitializationKind::CreateDirect(TypeRange.getBegin(), - LParenLoc, - RParenLoc), - ConstructorArgs); - - if (!Constructor) - return ExprError(); - - OwningExprResult Result = - BuildCXXTemporaryObjectExpr(Constructor, Ty, TyBeginLoc, - move_arg(ConstructorArgs), RParenLoc); - if (Result.isInvalid()) - return ExprError(); - - return MaybeBindToTemporary(Result.takeAs<Expr>()); + 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 @@ -530,10 +520,13 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, PlacementArgs.release(); ConstructorArgs.release(); ArraySizeE.release(); - return Owned(new (Context) CXXNewExpr(UseGlobal, OperatorNew, PlaceArgs, - NumPlaceArgs, ParenTypeId, ArraySize, Constructor, Init, - ConsArgs, NumConsArgs, OperatorDelete, ResultType, - StartLoc, Init ? ConstructorRParen : SourceLocation())); + return Owned(new (Context) CXXNewExpr(Context, UseGlobal, OperatorNew, + PlaceArgs, NumPlaceArgs, ParenTypeId, + ArraySize, Constructor, Init, + ConsArgs, NumConsArgs, OperatorDelete, + ResultType, StartLoc, + Init ? ConstructorRParen : + SourceLocation())); } /// CheckAllocatedType - Checks that a type is suitable as the allocated type @@ -636,19 +629,24 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, // FIXME: handle ambiguity - OverloadCandidateSet Candidates; + OverloadCandidateSet Candidates(StartLoc); for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); Alloc != AllocEnd; ++Alloc) { // Even member operator new/delete are implicitly treated as // static, so don't use AddMemberCandidate. - if (FunctionDecl *Fn = - dyn_cast<FunctionDecl>((*Alloc)->getUnderlyingDecl())) { - AddOverloadCandidate(Fn, Args, NumArgs, Candidates, - /*SuppressUserConversions=*/false); + + if (FunctionTemplateDecl *FnTemplate = + dyn_cast<FunctionTemplateDecl>((*Alloc)->getUnderlyingDecl())) { + AddTemplateOverloadCandidate(FnTemplate, Alloc.getAccess(), + /*ExplicitTemplateArgs=*/0, Args, NumArgs, + Candidates, + /*SuppressUserConversions=*/false); continue; - } - - // FIXME: Handle function templates + } + + FunctionDecl *Fn = cast<FunctionDecl>((*Alloc)->getUnderlyingDecl()); + AddOverloadCandidate(Fn, Alloc.getAccess(), Args, NumArgs, Candidates, + /*SuppressUserConversions=*/false); } // Do the resolution. @@ -779,12 +777,16 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, DeclContext::lookup_iterator Alloc, AllocEnd; for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); Alloc != AllocEnd; ++Alloc) { - // FIXME: Do we need to check for default arguments here? - FunctionDecl *Func = cast<FunctionDecl>(*Alloc); - if (Func->getNumParams() == 1 && + // Only look at non-template functions, as it is the predefined, + // non-templated allocation function we are trying to declare here. + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*Alloc)) { + QualType InitialParamType = Context.getCanonicalType( - Func->getParamDecl(0)->getType().getUnqualifiedType()) == Argument) - return; + Func->getParamDecl(0)->getType().getUnqualifiedType()); + // FIXME: Do we need to check for default arguments here? + if (Func->getNumParams() == 1 && InitialParamType == Argument) + return; + } } } @@ -812,7 +814,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, ParmVarDecl *Param = ParmVarDecl::Create(Context, Alloc, SourceLocation(), 0, Argument, /*TInfo=*/0, VarDecl::None, 0); - Alloc->setParams(Context, &Param, 1); + Alloc->setParams(&Param, 1); // FIXME: Also add this declaration to the IdentifierResolver, but // make sure it is at the end of the chain to coincide with the @@ -1487,9 +1489,9 @@ QualType Sema::CheckPointerToMemberOperands( static QualType TargetType(const ImplicitConversionSequence &ICS) { switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: - return ICS.Standard.getToType(); + return ICS.Standard.getToType(2); case ImplicitConversionSequence::UserDefinedConversion: - return ICS.UserDefined.After.getToType(); + return ICS.UserDefined.After.getToType(2); case ImplicitConversionSequence::AmbiguousConversion: return ICS.Ambiguous.getToType(); case ImplicitConversionSequence::EllipsisConversion: @@ -1587,7 +1589,7 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To, static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS, SourceLocation Loc) { Expr *Args[2] = { LHS, RHS }; - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(Loc); Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet); OverloadCandidateSet::iterator Best; @@ -1689,8 +1691,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (LVoid || RVoid) { // ... then the [l2r] conversions are performed on the second and third // operands ... - DefaultFunctionArrayConversion(LHS); - DefaultFunctionArrayConversion(RHS); + DefaultFunctionArrayLvalueConversion(LHS); + DefaultFunctionArrayLvalueConversion(RHS); LTy = LHS->getType(); RTy = RHS->getType(); @@ -1776,8 +1778,8 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // C++0x 5.16p6 // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard // conversions are performed on the second and third operands. - DefaultFunctionArrayConversion(LHS); - DefaultFunctionArrayConversion(RHS); + DefaultFunctionArrayLvalueConversion(LHS); + DefaultFunctionArrayLvalueConversion(RHS); LTy = LHS->getType(); RTy = RHS->getType(); @@ -1987,10 +1989,8 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!RT) return Owned(E); - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->hasTrivialDestructor()) - return Owned(E); - + // If this is the result of a call expression, our source might + // actually be a reference, in which case we shouldn't bind. if (CallExpr *CE = dyn_cast<CallExpr>(E)) { QualType Ty = CE->getCallee()->getType(); if (const PointerType *PT = Ty->getAs<PointerType>()) @@ -2000,6 +2000,13 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { if (FTy->getResultType()->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. + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (RD->hasTrivialDestructor()) + return Owned(E); + CXXTemporary *Temp = CXXTemporary::Create(Context, RD->getDestructor(Context)); ExprTemporaries.push_back(Temp); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ea8f4e3..0c5d8ef 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -470,11 +470,13 @@ Sema::ExprResult Sema::ActOnClassMessage( // now, we simply pass the "super" identifier through (which isn't consistent // with instance methods. if (isSuper) - return new (Context) ObjCMessageExpr(receiverName, Sel, returnType, Method, - lbrac, rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, receiverName, Sel, returnType, + Method, lbrac, rbrac, ArgExprs, + NumArgs); else - return new (Context) ObjCMessageExpr(ClassDecl, Sel, returnType, Method, - lbrac, rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, ClassDecl, Sel, returnType, + Method, lbrac, rbrac, ArgExprs, + NumArgs); } // ActOnInstanceMessage - used for both unary and keyword messages. @@ -492,7 +494,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // If necessary, apply function/array conversion to the receiver. // C99 6.7.5.3p[7,8]. - DefaultFunctionArrayConversion(RExpr); + DefaultFunctionArrayLvalueConversion(RExpr); QualType returnType; QualType ReceiverCType = @@ -521,8 +523,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, return true; returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, - rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, + Method, lbrac, rbrac, + ArgExprs, NumArgs); } // Handle messages to id. @@ -536,8 +539,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, lbrac, rbrac, returnType)) return true; returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, - rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, + Method, lbrac, rbrac, + ArgExprs, NumArgs); } // Handle messages to Class. @@ -582,8 +586,9 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, lbrac, rbrac, returnType)) return true; returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, - rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, + Method, lbrac, rbrac, + ArgExprs, NumArgs); } ObjCMethodDecl *Method = 0; @@ -665,7 +670,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, lbrac, rbrac, returnType)) return true; returnType = returnType.getNonReferenceType(); - return new (Context) ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, - rbrac, ArgExprs, NumArgs); + return new (Context) ObjCMessageExpr(Context, RExpr, Sel, returnType, Method, + lbrac, rbrac, ArgExprs, NumArgs); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index fd62e1a..7b4a417 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -66,40 +66,6 @@ static Expr *IsStringInit(Expr *Init, QualType DeclType, ASTContext &Context) { return 0; } -static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, - bool DirectInit, Sema &S) { - // Get the type before calling CheckSingleAssignmentConstraints(), since - // it can promote the expression. - QualType InitType = Init->getType(); - - if (S.getLangOptions().CPlusPlus) { - // FIXME: I dislike this error message. A lot. - if (S.PerformImplicitConversion(Init, DeclType, - Sema::AA_Initializing, DirectInit)) { - ImplicitConversionSequence ICS; - OverloadCandidateSet CandidateSet; - if (S.IsUserDefinedConversion(Init, DeclType, ICS.UserDefined, - CandidateSet, - true, false, false) != OR_Ambiguous) - return S.Diag(Init->getSourceRange().getBegin(), - diag::err_typecheck_convert_incompatible) - << DeclType << Init->getType() << Sema::AA_Initializing - << Init->getSourceRange(); - S.Diag(Init->getSourceRange().getBegin(), - diag::err_typecheck_convert_ambiguous) - << DeclType << Init->getType() << Init->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates, &Init, 1); - return true; - } - return false; - } - - Sema::AssignConvertType ConvTy = - S.CheckSingleAssignmentConstraints(DeclType, Init); - return S.DiagnoseAssignmentResult(ConvTy, Init->getLocStart(), DeclType, - InitType, Init, Sema::AA_Initializing); -} - static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) { // Get the length of the string as parsed. uint64_t StrLength = @@ -174,47 +140,57 @@ class InitListChecker { std::map<InitListExpr *, InitListExpr *> SyntacticToSemantic; InitListExpr *FullyStructuredList; - void CheckImplicitInitList(InitListExpr *ParentIList, QualType T, + void CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); - void CheckExplicitInitList(InitListExpr *IList, QualType &T, + void CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); - void CheckListElementTypes(InitListExpr *IList, QualType &DeclType, + void CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); - void CheckSubElementType(InitListExpr *IList, QualType ElemType, + void CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); - void CheckScalarType(InitListExpr *IList, QualType DeclType, + void CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); - void CheckReferenceType(InitListExpr *IList, QualType DeclType, + void CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); - void CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned &Index, + void CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); - void CheckStructUnionTypes(InitListExpr *IList, QualType DeclType, + void CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, bool TopLevelObject = false); - void CheckArrayType(InitListExpr *IList, QualType &DeclType, + void CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex); - bool CheckDesignatedInitializer(InitListExpr *IList, DesignatedInitExpr *DIE, + bool CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, RecordDecl::field_iterator *NextField, @@ -433,7 +409,8 @@ InitListChecker::InitListChecker(Sema &S, const InitializedEntity &Entity, unsigned newStructuredIndex = 0; FullyStructuredList = getStructuredSubobjectInit(IL, newIndex, T, 0, 0, IL->getSourceRange()); - CheckExplicitInitList(IL, T, newIndex, FullyStructuredList, newStructuredIndex, + CheckExplicitInitList(Entity, IL, T, newIndex, + FullyStructuredList, newStructuredIndex, /*TopLevelObject=*/true); if (!hadError) { @@ -470,7 +447,8 @@ int InitListChecker::numStructUnionElements(QualType DeclType) { return InitializableMembers - structDecl->hasFlexibleArrayMember(); } -void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList, +void InitListChecker::CheckImplicitInitList(const InitializedEntity &Entity, + InitListExpr *ParentIList, QualType T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, @@ -504,7 +482,8 @@ void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList, // Check the element types and build the structural subobject. unsigned StartIndex = Index; - CheckListElementTypes(ParentIList, T, false, Index, + CheckListElementTypes(Entity, ParentIList, T, + /*SubobjectIsDesignatorContext=*/false, Index, StructuredSubobjectInitList, StructuredSubobjectInitIndex, TopLevelObject); @@ -520,7 +499,8 @@ void InitListChecker::CheckImplicitInitList(InitListExpr *ParentIList, } } -void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T, +void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, + InitListExpr *IList, QualType &T, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex, @@ -528,10 +508,10 @@ void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T, assert(IList->isExplicit() && "Illegal Implicit InitListExpr"); SyntacticToSemantic[IList] = StructuredList; StructuredList->setSyntacticForm(IList); - CheckListElementTypes(IList, T, true, Index, StructuredList, - StructuredIndex, TopLevelObject); - IList->setType(T); - StructuredList->setType(T); + CheckListElementTypes(Entity, IList, T, /*SubobjectIsDesignatorContext=*/true, + Index, StructuredList, StructuredIndex, TopLevelObject); + IList->setType(T.getNonReferenceType()); + StructuredList->setType(T.getNonReferenceType()); if (hadError) return; @@ -580,7 +560,8 @@ void InitListChecker::CheckExplicitInitList(InitListExpr *IList, QualType &T, << CodeModificationHint::CreateRemoval(IList->getLocEnd()); } -void InitListChecker::CheckListElementTypes(InitListExpr *IList, +void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, bool SubobjectIsDesignatorContext, unsigned &Index, @@ -588,13 +569,15 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, unsigned &StructuredIndex, bool TopLevelObject) { if (DeclType->isScalarType()) { - CheckScalarType(IList, DeclType, Index, StructuredList, StructuredIndex); + CheckScalarType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); } else if (DeclType->isVectorType()) { - CheckVectorType(IList, DeclType, Index, StructuredList, StructuredIndex); + CheckVectorType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); } else if (DeclType->isAggregateType()) { if (DeclType->isRecordType()) { RecordDecl *RD = DeclType->getAs<RecordType>()->getDecl(); - CheckStructUnionTypes(IList, DeclType, RD->field_begin(), + CheckStructUnionTypes(Entity, IList, DeclType, RD->field_begin(), SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex, TopLevelObject); @@ -602,7 +585,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, llvm::APSInt Zero( SemaRef.Context.getTypeSize(SemaRef.Context.getSizeType()), false); - CheckArrayType(IList, DeclType, Zero, SubobjectIsDesignatorContext, Index, + CheckArrayType(Entity, IList, DeclType, Zero, + SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex); } else assert(0 && "Aggregate that isn't a structure or array?!"); @@ -625,7 +609,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, << DeclType << IList->getSourceRange(); hadError = true; } else if (DeclType->isReferenceType()) { - CheckReferenceType(IList, DeclType, Index, StructuredList, StructuredIndex); + CheckReferenceType(Entity, IList, DeclType, Index, + StructuredList, StructuredIndex); } else { // In C, all types are either scalars or aggregates, but // additional handling is needed here for C++ (and possibly others?). @@ -633,7 +618,8 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, } } -void InitListChecker::CheckSubElementType(InitListExpr *IList, +void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, + InitListExpr *IList, QualType ElemType, unsigned &Index, InitListExpr *StructuredList, @@ -646,7 +632,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, = getStructuredSubobjectInit(IList, Index, ElemType, StructuredList, StructuredIndex, SubInitList->getSourceRange()); - CheckExplicitInitList(SubInitList, ElemType, newIndex, + CheckExplicitInitList(Entity, SubInitList, ElemType, newIndex, newStructuredList, newStructuredIndex); ++StructuredIndex; ++Index; @@ -655,9 +641,11 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, UpdateStructuredListElement(StructuredList, StructuredIndex, Str); ++Index; } else if (ElemType->isScalarType()) { - CheckScalarType(IList, ElemType, Index, StructuredList, StructuredIndex); + CheckScalarType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); } else if (ElemType->isReferenceType()) { - CheckReferenceType(IList, ElemType, Index, StructuredList, StructuredIndex); + CheckReferenceType(Entity, IList, ElemType, Index, + StructuredList, StructuredIndex); } else { if (SemaRef.getLangOptions().CPlusPlus) { // C++ [dcl.init.aggr]p12: @@ -665,17 +653,21 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, // initializing the aggregate member with an ini- tializer from // an initializer-list. If the initializer can initialize a // member, the member is initialized. [...] - ImplicitConversionSequence ICS - = SemaRef.TryCopyInitialization(expr, ElemType, - /*SuppressUserConversions=*/false, - /*ForceRValue=*/false, - /*InOverloadResolution=*/false); - - if (!ICS.isBad()) { - if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS, - Sema::AA_Initializing)) + + // FIXME: Better EqualLoc? + InitializationKind Kind = + InitializationKind::CreateCopy(expr->getLocStart(), SourceLocation()); + InitializationSequence Seq(SemaRef, Entity, Kind, &expr, 1); + + if (Seq) { + Sema::OwningExprResult Result = + Seq.Perform(SemaRef, Entity, Kind, + Sema::MultiExprArg(SemaRef, (void **)&expr, 1)); + if (Result.isInvalid()) hadError = true; - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + + UpdateStructuredListElement(StructuredList, StructuredIndex, + Result.takeAs<Expr>()); ++Index; return; } @@ -707,13 +699,15 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, // considered for the initialization of the first member of // the subaggregate. if (ElemType->isAggregateType() || ElemType->isVectorType()) { - CheckImplicitInitList(IList, ElemType, Index, StructuredList, + CheckImplicitInitList(Entity, IList, ElemType, Index, StructuredList, StructuredIndex); ++StructuredIndex; } else { // We cannot initialize this element, so let // PerformCopyInitialization produce the appropriate diagnostic. - SemaRef.PerformCopyInitialization(expr, ElemType, Sema::AA_Initializing); + SemaRef.PerformCopyInitialization(Entity, SourceLocation(), + SemaRef.Owned(expr)); + IList->setInit(Index, 0); hadError = true; ++Index; ++StructuredIndex; @@ -721,7 +715,8 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList, } } -void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType, +void InitListChecker::CheckScalarType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { @@ -745,17 +740,26 @@ void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType, return; } - Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer. - if (CheckSingleInitializer(expr, DeclType, false, SemaRef)) + Sema::OwningExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr)); + + Expr *ResultExpr = 0; + + if (Result.isInvalid()) hadError = true; // types weren't compatible. - else if (savExpr != expr) { - // The type was promoted, update initializer list. - IList->setInit(Index, expr); + else { + ResultExpr = Result.takeAs<Expr>(); + + if (ResultExpr != expr) { + // The type was promoted, update initializer list. + IList->setInit(Index, ResultExpr); + } } if (hadError) ++StructuredIndex; else - UpdateStructuredListElement(StructuredList, StructuredIndex, expr); + UpdateStructuredListElement(StructuredList, StructuredIndex, ResultExpr); ++Index; } else { SemaRef.Diag(IList->getLocStart(), diag::err_empty_scalar_initializer) @@ -767,7 +771,8 @@ void InitListChecker::CheckScalarType(InitListExpr *IList, QualType DeclType, } } -void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType, +void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { @@ -782,17 +787,16 @@ void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType, return; } - Expr *savExpr = expr; // Might be promoted by CheckSingleInitializer. - if (SemaRef.CheckReferenceInit(expr, DeclType, - /*FIXME:*/expr->getLocStart(), - /*SuppressUserConversions=*/false, - /*AllowExplicit=*/false, - /*ForceRValue=*/false)) + Sema::OwningExprResult Result = + SemaRef.PerformCopyInitialization(Entity, expr->getLocStart(), + SemaRef.Owned(expr)); + + if (Result.isInvalid()) hadError = true; - else if (savExpr != expr) { - // The type was promoted, update initializer list. - IList->setInit(Index, expr); - } + + expr = Result.takeAs<Expr>(); + IList->setInit(Index, expr); + if (hadError) ++StructuredIndex; else @@ -814,7 +818,8 @@ void InitListChecker::CheckReferenceType(InitListExpr *IList, QualType DeclType, } } -void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, +void InitListChecker::CheckVectorType(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, unsigned &Index, InitListExpr *StructuredList, unsigned &StructuredIndex) { @@ -825,22 +830,33 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, QualType elementType = VT->getElementType(); if (!SemaRef.getLangOptions().OpenCL) { + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + for (unsigned i = 0; i < maxElements; ++i, ++numEltsInit) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) break; - CheckSubElementType(IList, elementType, Index, + + ElementEntity.setElementIndex(Index); + CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); } } else { + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + // OpenCL initializers allows vectors to be constructed from vectors. for (unsigned i = 0; i < maxElements; ++i) { // Don't attempt to go past the end of the init list if (Index >= IList->getNumInits()) break; + + ElementEntity.setElementIndex(Index); + QualType IType = IList->getInit(Index)->getType(); if (!IType->isVectorType()) { - CheckSubElementType(IList, elementType, Index, + CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++numEltsInit; } else { @@ -848,7 +864,7 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, unsigned numIElts = IVT->getNumElements(); QualType VecType = SemaRef.Context.getExtVectorType(elementType, numIElts); - CheckSubElementType(IList, VecType, Index, + CheckSubElementType(ElementEntity, IList, VecType, Index, StructuredList, StructuredIndex); numEltsInit += numIElts; } @@ -864,7 +880,8 @@ void InitListChecker::CheckVectorType(InitListExpr *IList, QualType DeclType, } } -void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, +void InitListChecker::CheckArrayType(const InitializedEntity &Entity, + InitListExpr *IList, QualType &DeclType, llvm::APSInt elementIndex, bool SubobjectIsDesignatorContext, unsigned &Index, @@ -925,7 +942,7 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, // Handle this designated initializer. elementIndex will be // updated to be the next array element we'll initialize. - if (CheckDesignatedInitializer(IList, DIE, 0, + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, 0, &elementIndex, Index, StructuredList, StructuredIndex, true, false)) { @@ -952,8 +969,11 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, if (maxElementsKnown && elementIndex == maxElements) break; + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, StructuredIndex, + Entity); // Check this element. - CheckSubElementType(IList, elementType, Index, + CheckSubElementType(ElementEntity, IList, elementType, Index, StructuredList, StructuredIndex); ++elementIndex; @@ -978,7 +998,8 @@ void InitListChecker::CheckArrayType(InitListExpr *IList, QualType &DeclType, } } -void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, +void InitListChecker::CheckStructUnionTypes(const InitializedEntity &Entity, + InitListExpr *IList, QualType DeclType, RecordDecl::field_iterator Field, bool SubobjectIsDesignatorContext, @@ -1027,7 +1048,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, // Handle this designated initializer. Field will be updated to // the next field that we'll be initializing. - if (CheckDesignatedInitializer(IList, DIE, 0, + if (CheckDesignatedInitializer(Entity, IList, DIE, 0, DeclType, &Field, 0, Index, StructuredList, StructuredIndex, true, TopLevelObject)) @@ -1056,7 +1077,9 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, continue; } - CheckSubElementType(IList, Field->getType(), Index, + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, StructuredIndex); InitializedSomething = true; @@ -1092,12 +1115,15 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, << *Field; } + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + if (isa<InitListExpr>(IList->getInit(Index))) - CheckSubElementType(IList, Field->getType(), Index, StructuredList, - StructuredIndex); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); else - CheckImplicitInitList(IList, Field->getType(), Index, StructuredList, - StructuredIndex); + CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index, + StructuredList, StructuredIndex); } /// \brief Expand a field designator that refers to a member of an @@ -1194,7 +1220,8 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef, /// /// @returns true if there was an error, false otherwise. bool -InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, +InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, + InitListExpr *IList, DesignatedInitExpr *DIE, unsigned DesigIdx, QualType &CurrentObjectType, @@ -1215,7 +1242,7 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, unsigned OldIndex = Index; IList->setInit(OldIndex, DIE->getInit()); - CheckSubElementType(IList, CurrentObjectType, Index, + CheckSubElementType(Entity, IList, CurrentObjectType, Index, StructuredList, StructuredIndex); // Restore the designated initializer expression in the syntactic @@ -1423,8 +1450,12 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, unsigned newStructuredIndex = FieldIndex; unsigned OldIndex = Index; IList->setInit(Index, DIE->getInit()); - CheckSubElementType(IList, Field->getType(), Index, + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + CheckSubElementType(MemberEntity, IList, Field->getType(), Index, StructuredList, newStructuredIndex); + IList->setInit(OldIndex, DIE); if (hadError && !prevHadError) { ++Field; @@ -1438,8 +1469,12 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // Recurse to check later designated subobjects. QualType FieldType = (*Field)->getType(); unsigned newStructuredIndex = FieldIndex; - if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, FieldType, 0, 0, - Index, StructuredList, newStructuredIndex, + + InitializedEntity MemberEntity = + InitializedEntity::InitializeMember(*Field, &Entity); + if (CheckDesignatedInitializer(MemberEntity, IList, DIE, DesigIdx + 1, + FieldType, 0, 0, Index, + StructuredList, newStructuredIndex, true, false)) return true; } @@ -1467,7 +1502,8 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // Check the remaining fields within this class/struct/union subobject. bool prevHadError = hadError; - CheckStructUnionTypes(IList, CurrentObjectType, Field, false, Index, + + CheckStructUnionTypes(Entity, IList, CurrentObjectType, Field, false, Index, StructuredList, FieldIndex); return hadError && !prevHadError; } @@ -1552,12 +1588,19 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // Move to the next designator unsigned ElementIndex = DesignatedStartIndex.getZExtValue(); unsigned OldIndex = Index; + + InitializedEntity ElementEntity = + InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); + while (DesignatedStartIndex <= DesignatedEndIndex) { // Recurse to check later designated subobjects. QualType ElementType = AT->getElementType(); Index = OldIndex; - if (CheckDesignatedInitializer(IList, DIE, DesigIdx + 1, ElementType, 0, 0, - Index, StructuredList, ElementIndex, + + ElementEntity.setElementIndex(ElementIndex); + if (CheckDesignatedInitializer(ElementEntity, IList, DIE, DesigIdx + 1, + ElementType, 0, 0, Index, + StructuredList, ElementIndex, (DesignatedStartIndex == DesignatedEndIndex), false)) return true; @@ -1581,7 +1624,8 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // Check the remaining elements within this array subobject. bool prevHadError = hadError; - CheckArrayType(IList, CurrentObjectType, DesignatedStartIndex, false, Index, + CheckArrayType(Entity, IList, CurrentObjectType, DesignatedStartIndex, + /*SubobjectIsDesignatorContext=*/false, Index, StructuredList, ElementIndex); return hadError && !prevHadError; } @@ -1628,7 +1672,7 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, = new (SemaRef.Context) InitListExpr(InitRange.getBegin(), 0, 0, InitRange.getEnd()); - Result->setType(CurrentObjectType); + Result->setType(CurrentObjectType.getNonReferenceType()); // Pre-allocate storage for the structured initializer list. unsigned NumElements = 0; @@ -1927,7 +1971,8 @@ void InitializationSequence::AddAddressOverloadResolutionStep( Step S; S.Kind = SK_ResolveAddressOfOverloadedFunction; S.Type = Function->getType(); - S.Function = Function; + // Access is currently ignored for these. + S.Function = DeclAccessPair::make(Function, AccessSpecifier(0)); Steps.push_back(S); } @@ -1948,11 +1993,12 @@ void InitializationSequence::AddReferenceBindingStep(QualType T, } void InitializationSequence::AddUserConversionStep(FunctionDecl *Function, + AccessSpecifier Access, QualType T) { Step S; S.Kind = SK_UserConversion; S.Type = T; - S.Function = Function; + S.Function = DeclAccessPair::make(Function, Access); Steps.push_back(S); } @@ -1985,11 +2031,12 @@ void InitializationSequence::AddListInitializationStep(QualType T) { void InitializationSequence::AddConstructorInitializationStep( CXXConstructorDecl *Constructor, + AccessSpecifier Access, QualType T) { Step S; S.Kind = SK_ConstructorInitialization; S.Type = T; - S.Function = Constructor; + S.Function = DeclAccessPair::make(Constructor, Access); Steps.push_back(S); } @@ -2129,10 +2176,13 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, + S.AddTemplateOverloadCandidate(ConstructorTmpl, + ConstructorTmpl->getAccess(), + /*ExplicitArgs*/ 0, &Initializer, 1, CandidateSet); else - S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet); + S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + &Initializer, 1, CandidateSet); } } } @@ -2172,11 +2222,12 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, if ((AllowExplicit || !Conv->isExplicit()) && (AllowRValues || Conv->getConversionType()->isLValueReferenceType())){ if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, Initializer, + S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), + ActingDC, Initializer, ToType, CandidateSet); else - S.AddConversionCandidate(Conv, ActingDC, Initializer, cv1T1, - CandidateSet); + S.AddConversionCandidate(Conv, I.getAccess(), ActingDC, + Initializer, cv1T1, CandidateSet); } } } @@ -2198,7 +2249,8 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S, T2 = cv1T1; // Add the user-defined conversion step. - Sequence.AddUserConversionStep(Function, T2.getNonReferenceType()); + Sequence.AddUserConversionStep(Function, Best->getAccess(), + T2.getNonReferenceType()); // Determine whether we need to perform derived-to-base or // cv-qualification adjustments. @@ -2281,16 +2333,20 @@ static void TryReferenceInitialization(Sema &S, // - is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or // - // Per C++ [over.best.ics]p2, we ignore whether the lvalue is a + // Per C++ [over.best.ics]p2, we don't diagnose whether the lvalue is a // bit-field when we're determining whether the reference initialization - // can occur. This property will be checked by PerformInitialization. + // can occur. However, we do pay attention to whether it is a bit-field + // to decide whether we're actually binding to a temporary created from + // the bit-field. if (DerivedToBase) Sequence.AddDerivedToBaseCastStep( S.Context.getQualifiedType(T1, T2Quals), /*isLValue=*/true); if (T1Quals != T2Quals) Sequence.AddQualificationConversionStep(cv1T1, /*IsLValue=*/true); - Sequence.AddReferenceBindingStep(cv1T1, /*bindingTemporary=*/false); + bool BindingTemporary = T1Quals.hasConst() && !T1Quals.hasVolatile() && + (Initializer->getBitField() || Initializer->refersToVectorElement()); + Sequence.AddReferenceBindingStep(cv1T1, BindingTemporary); return; } @@ -2319,7 +2375,7 @@ static void TryReferenceInitialization(Sema &S, // 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. - if (!((isLValueRef && T1Quals.hasConst()) || + if (!((isLValueRef && T1Quals.hasConst() && !T1Quals.hasVolatile()) || (isRValueRef && InitLvalue != Expr::LV_Valid))) { if (ConvOvlResult && !Sequence.getFailedCandidateSet().empty()) Sequence.SetOverloadFailure( @@ -2489,10 +2545,13 @@ static void TryConstructorInitialization(Sema &S, if (!Constructor->isInvalidDecl() && (AllowExplicit || !Constructor->isExplicit())) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, + S.AddTemplateOverloadCandidate(ConstructorTmpl, + ConstructorTmpl->getAccess(), + /*ExplicitArgs*/ 0, Args, NumArgs, CandidateSet); else - S.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet); + S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + Args, NumArgs, CandidateSet); } } @@ -2507,14 +2566,26 @@ static void TryConstructorInitialization(Sema &S, Result); return; } - + + // C++0x [dcl.init]p6: + // If a program calls for the default initialization of an object + // of a const-qualified type T, T shall be a class type with a + // user-provided default constructor. + if (Kind.getKind() == InitializationKind::IK_Default && + Entity.getType().isConstQualified() && + cast<CXXConstructorDecl>(Best->Function)->isImplicit()) { + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } + // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. if (Kind.getKind() == InitializationKind::IK_Copy) { - Sequence.AddUserConversionStep(Best->Function, DestType); + Sequence.AddUserConversionStep(Best->Function, Best->getAccess(), DestType); } else { Sequence.AddConstructorInitializationStep( cast<CXXConstructorDecl>(Best->Function), + Best->getAccess(), DestType); } } @@ -2579,10 +2650,7 @@ static void TryDefaultInitialization(Sema &S, // - if T is a (possibly cv-qualified) class type (Clause 9), the default // constructor for T is called (and the initialization is ill-formed if // T has no accessible default constructor); - if (DestType->isRecordType()) { - // FIXME: If a program calls for the default initialization of an object of - // a const-qualified type T, T shall be a class type with a user-provided - // default constructor. + if (DestType->isRecordType() && S.getLangOptions().CPlusPlus) { return TryConstructorInitialization(S, Entity, Kind, 0, 0, DestType, Sequence); } @@ -2593,7 +2661,7 @@ static void TryDefaultInitialization(Sema &S, // If a program calls for the default initialization of an object of // a const-qualified type T, T shall be a class type with a user-provided // default constructor. - if (DestType.isConstQualified()) + if (DestType.isConstQualified() && S.getLangOptions().CPlusPlus) Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); } @@ -2647,10 +2715,13 @@ static void TryUserDefinedConversion(Sema &S, if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, + S.AddTemplateOverloadCandidate(ConstructorTmpl, + ConstructorTmpl->getAccess(), + /*ExplicitArgs*/ 0, &Initializer, 1, CandidateSet); else - S.AddOverloadCandidate(Constructor, &Initializer, 1, CandidateSet); + S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + &Initializer, 1, CandidateSet); } } } @@ -2686,12 +2757,12 @@ static void TryUserDefinedConversion(Sema &S, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - S.AddTemplateConversionCandidate(ConvTemplate, ActingDC, - Initializer, DestType, + S.AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), + ActingDC, Initializer, DestType, CandidateSet); else - S.AddConversionCandidate(Conv, ActingDC, Initializer, DestType, - CandidateSet); + S.AddConversionCandidate(Conv, I.getAccess(), ActingDC, + Initializer, DestType, CandidateSet); } } } @@ -2712,13 +2783,13 @@ static void TryUserDefinedConversion(Sema &S, if (isa<CXXConstructorDecl>(Function)) { // Add the user-defined conversion step. Any cv-qualification conversion is // subsumed by the initialization. - Sequence.AddUserConversionStep(Function, DestType); + Sequence.AddUserConversionStep(Function, Best->getAccess(), DestType); return; } // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getResultType().getNonReferenceType(); - Sequence.AddUserConversionStep(Function, ConvType); + Sequence.AddUserConversionStep(Function, Best->getAccess(), ConvType); // If the conversion following the call to the conversion function is // interesting, add it as a separate step. @@ -2758,7 +2829,8 @@ InitializationSequence::InitializationSequence(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Expr **Args, - unsigned NumArgs) { + unsigned NumArgs) + : FailedCandidateSet(Kind.getLocation()) { ASTContext &Context = S.Context; // C++0x [dcl.init]p16: @@ -2934,15 +3006,15 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity, bool IsCopy) { switch (Entity.getKind()) { case InitializedEntity::EK_Result: - case InitializedEntity::EK_Exception: + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: return !IsCopy; case InitializedEntity::EK_New: case InitializedEntity::EK_Variable: case InitializedEntity::EK_Base: - case InitializedEntity::EK_Member: - case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: + case InitializedEntity::EK_Exception: return false; case InitializedEntity::EK_Parameter: @@ -2960,6 +3032,8 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Sema::OwningExprResult CurInit) { + Expr *CurInitExpr = (Expr *)CurInit.get(); + SourceLocation Loc; switch (Entity.getKind()) { @@ -2980,6 +3054,14 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, Loc = Entity.getDecl()->getLocation(); break; + case InitializedEntity::EK_ArrayElement: + case InitializedEntity::EK_Member: + if (Entity.getType()->isReferenceType() || + Kind.getKind() != InitializationKind::IK_Copy) + return move(CurInit); + Loc = CurInitExpr->getLocStart(); + break; + case InitializedEntity::EK_Parameter: // FIXME: Do we need this initialization for a parameter? return move(CurInit); @@ -2987,14 +3069,11 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, case InitializedEntity::EK_New: case InitializedEntity::EK_Temporary: case InitializedEntity::EK_Base: - case InitializedEntity::EK_Member: - case InitializedEntity::EK_ArrayElement: case InitializedEntity::EK_VectorElement: // We don't need to copy for any of these initialized entities. return move(CurInit); } - Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = 0; if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>()) Class = cast<CXXRecordDecl>(Record->getDecl()); @@ -3006,7 +3085,7 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, = S.Context.DeclarationNames.getCXXConstructorName( S.Context.getCanonicalType(S.Context.getTypeDeclType(Class))); DeclContext::lookup_iterator Con, ConEnd; - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(Loc); for (llvm::tie(Con, ConEnd) = Class->lookup(ConstructorName); Con != ConEnd; ++Con) { // Find the constructor (which may be a template). @@ -3015,7 +3094,8 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, !Constructor->isCopyConstructor()) continue; - S.AddOverloadCandidate(Constructor, &CurInitExpr, 1, CandidateSet); + S.AddOverloadCandidate(Constructor, Constructor->getAccess(), + &CurInitExpr, 1, CandidateSet); } OverloadCandidateSet::iterator Best; @@ -3111,6 +3191,9 @@ InitializationSequence::Perform(Sema &S, if (Kind.getKind() == InitializationKind::IK_Copy || Kind.isExplicitCast()) return Sema::OwningExprResult(S, Args.release()[0]); + if (Args.size() == 0) + return S.Owned((Expr *)0); + unsigned NumArgs = Args.size(); return S.Owned(new (S.Context) ParenListExpr(S.Context, SourceLocation(), @@ -3176,7 +3259,9 @@ InitializationSequence::Perform(Sema &S, case SK_ResolveAddressOfOverloadedFunction: // Overload resolution determined which function invoke; update the // initializer to reflect that choice. - CurInit = S.FixOverloadedFunctionReference(move(CurInit), Step->Function); + // Access control was done in overload resolution. + CurInit = S.FixOverloadedFunctionReference(move(CurInit), + cast<FunctionDecl>(Step->Function.getDecl())); break; case SK_CastDerivedToBaseRValue: @@ -3209,21 +3294,30 @@ InitializationSequence::Perform(Sema &S, S.Diag(BitField->getLocation(), diag::note_bitfield_decl); return S.ExprError(); } + + if (CurInitExpr->refersToVectorElement()) { + // References cannot bind to vector elements. + S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element) + << Entity.getType().isVolatileQualified() + << CurInitExpr->getSourceRange(); + return S.ExprError(); + } // Reference binding does not have any corresponding ASTs. // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) return S.ExprError(); + break; - + case SK_BindReferenceToTemporary: + // Reference binding does not have any corresponding ASTs. + // Check exception specifications if (S.CheckExceptionSpecCompatibility(CurInitExpr, DestType)) return S.ExprError(); - // FIXME: At present, we have no AST to describe when we need to make a - // temporary to bind a reference to. We should. break; case SK_UserConversion: { @@ -3231,13 +3325,14 @@ InitializationSequence::Perform(Sema &S, // or a conversion function. CastExpr::CastKind CastKind = CastExpr::CK_Unknown; bool IsCopy = false; - if (CXXConstructorDecl *Constructor - = dyn_cast<CXXConstructorDecl>(Step->Function)) { + FunctionDecl *Fn = cast<FunctionDecl>(Step->Function.getDecl()); + AccessSpecifier FnAccess = Step->Function.getAccess(); + if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Fn)) { // Build a call to the selected constructor. ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); SourceLocation Loc = CurInitExpr->getLocStart(); CurInit.release(); // Ownership transferred into MultiExprArg, below. - + // Determine the arguments required to actually perform the constructor // call. if (S.CompleteConstructorCall(Constructor, @@ -3252,6 +3347,8 @@ InitializationSequence::Perform(Sema &S, move_arg(ConstructorArgs)); if (CurInit.isInvalid()) return S.ExprError(); + + S.CheckConstructorAccess(Kind.getLocation(), Constructor, FnAccess); CastKind = CastExpr::CK_ConstructorConversion; QualType Class = S.Context.getTypeDeclType(Constructor->getParent()); @@ -3260,8 +3357,11 @@ InitializationSequence::Perform(Sema &S, IsCopy = true; } else { // Build a call to the conversion function. - CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Step->Function); + CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Fn); + S.CheckMemberOperatorAccess(Kind.getLocation(), CurInitExpr, + Conversion, FnAccess); + // FIXME: Should we move this initialization into a separate // derived-to-base conversion? I believe the answer is "no", because // we don't want to turn off access control here for c-style casts. @@ -3326,8 +3426,8 @@ InitializationSequence::Perform(Sema &S, case SK_ConstructorInitialization: { CXXConstructorDecl *Constructor - = cast<CXXConstructorDecl>(Step->Function); - + = cast<CXXConstructorDecl>(Step->Function.getDecl()); + // Build a call to the selected constructor. ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); SourceLocation Loc = Kind.getLocation(); @@ -3342,9 +3442,13 @@ InitializationSequence::Perform(Sema &S, CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(), Constructor, move_arg(ConstructorArgs), - ConstructorInitRequiresZeroInit); + ConstructorInitRequiresZeroInit, + Entity.getKind() == InitializedEntity::EK_Base); if (CurInit.isInvalid()) return S.ExprError(); + + // Only check access if all of that succeeded. + S.CheckConstructorAccess(Loc, Constructor, Step->Function.getAccess()); bool Elidable = cast<CXXConstructExpr>((Expr *)CurInit.get())->isElidable(); @@ -3422,8 +3526,13 @@ bool InitializationSequence::Diagnose(Sema &S, QualType DestType = Entity.getType(); switch (Failure) { case FK_TooManyInitsForReference: - S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) - << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); + // FIXME: Customize for the initialized entity? + if (NumArgs == 0) + S.Diag(Kind.getLocation(), diag::err_reference_without_init) + << DestType.getNonReferenceType(); + else // FIXME: diagnostic below could be better! + S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits) + << SourceRange(Args[0]->getLocStart(), Args[NumArgs - 1]->getLocEnd()); break; case FK_ArrayNeedsInitList: @@ -3492,6 +3601,7 @@ bool InitializationSequence::Diagnose(Sema &S, Failure == FK_NonConstLValueReferenceBindingToTemporary ? diag::err_lvalue_reference_bind_to_temporary : diag::err_lvalue_reference_bind_to_unrelated) + << DestType.getNonReferenceType().isVolatileQualified() << DestType.getNonReferenceType() << Args[0]->getType() << Args[0]->getSourceRange(); @@ -3567,6 +3677,45 @@ bool InitializationSequence::Diagnose(Sema &S, break; case OR_No_Viable_Function: + if (Kind.getKind() == InitializationKind::IK_Default && + (Entity.getKind() == InitializedEntity::EK_Base || + Entity.getKind() == InitializedEntity::EK_Member) && + isa<CXXConstructorDecl>(S.CurContext)) { + // This is implicit default initialization of a member or + // base within a constructor. If no viable function was + // found, notify the user that she needs to explicitly + // initialize this base/member. + CXXConstructorDecl *Constructor + = cast<CXXConstructorDecl>(S.CurContext); + if (Entity.getKind() == InitializedEntity::EK_Base) { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*base=*/0 + << Entity.getType(); + + RecordDecl *BaseDecl + = Entity.getBaseSpecifier()->getType()->getAs<RecordType>() + ->getDecl(); + S.Diag(BaseDecl->getLocation(), diag::note_previous_decl) + << S.Context.getTagDeclType(BaseDecl); + } else { + S.Diag(Kind.getLocation(), diag::err_missing_default_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*member=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_field_decl); + + if (const RecordType *Record + = Entity.getType()->getAs<RecordType>()) + S.Diag(Record->getDecl()->getLocation(), + diag::note_previous_decl) + << S.Context.getTagDeclType(Record->getDecl()); + } + break; + } + S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates, @@ -3597,14 +3746,217 @@ bool InitializationSequence::Diagnose(Sema &S, } case FK_DefaultInitOfConst: - S.Diag(Kind.getLocation(), diag::err_default_init_const) - << DestType; + if (Entity.getKind() == InitializedEntity::EK_Member && + isa<CXXConstructorDecl>(S.CurContext)) { + // This is implicit default-initialization of a const member in + // a constructor. Complain that it needs to be explicitly + // initialized. + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext); + S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor) + << Constructor->isImplicit() + << S.Context.getTypeDeclType(Constructor->getParent()) + << /*const=*/1 + << Entity.getName(); + S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl) + << Entity.getName(); + } else { + S.Diag(Kind.getLocation(), diag::err_default_init_const) + << DestType << (bool)DestType->getAs<RecordType>(); + } break; } return true; } +void InitializationSequence::dump(llvm::raw_ostream &OS) const { + switch (SequenceKind) { + case FailedSequence: { + OS << "Failed sequence: "; + switch (Failure) { + case FK_TooManyInitsForReference: + OS << "too many initializers for reference"; + break; + + case FK_ArrayNeedsInitList: + OS << "array requires initializer list"; + break; + + case FK_ArrayNeedsInitListOrStringLiteral: + OS << "array requires initializer list or string literal"; + break; + + case FK_AddressOfOverloadFailed: + OS << "address of overloaded function failed"; + break; + + case FK_ReferenceInitOverloadFailed: + OS << "overload resolution for reference initialization failed"; + break; + + case FK_NonConstLValueReferenceBindingToTemporary: + OS << "non-const lvalue reference bound to temporary"; + break; + + case FK_NonConstLValueReferenceBindingToUnrelated: + OS << "non-const lvalue reference bound to unrelated type"; + break; + + case FK_RValueReferenceBindingToLValue: + OS << "rvalue reference bound to an lvalue"; + break; + + case FK_ReferenceInitDropsQualifiers: + OS << "reference initialization drops qualifiers"; + break; + + case FK_ReferenceInitFailed: + OS << "reference initialization failed"; + break; + + case FK_ConversionFailed: + OS << "conversion failed"; + break; + + case FK_TooManyInitsForScalar: + OS << "too many initializers for scalar"; + break; + + case FK_ReferenceBindingToInitList: + OS << "referencing binding to initializer list"; + break; + + case FK_InitListBadDestinationType: + OS << "initializer list for non-aggregate, non-scalar type"; + break; + + case FK_UserConversionOverloadFailed: + OS << "overloading failed for user-defined conversion"; + break; + + case FK_ConstructorOverloadFailed: + OS << "constructor overloading failed"; + break; + + case FK_DefaultInitOfConst: + OS << "default initialization of a const variable"; + break; + } + OS << '\n'; + return; + } + + case DependentSequence: + OS << "Dependent sequence: "; + return; + + case UserDefinedConversion: + OS << "User-defined conversion sequence: "; + break; + + case ConstructorInitialization: + OS << "Constructor initialization sequence: "; + break; + + case ReferenceBinding: + OS << "Reference binding: "; + break; + + case ListInitialization: + OS << "List initialization: "; + break; + + case ZeroInitialization: + OS << "Zero initialization\n"; + return; + + case NoInitialization: + OS << "No initialization\n"; + return; + + case StandardConversion: + OS << "Standard conversion: "; + break; + + case CAssignment: + OS << "C assignment: "; + break; + + case StringInit: + OS << "String initialization: "; + break; + } + + for (step_iterator S = step_begin(), SEnd = step_end(); S != SEnd; ++S) { + if (S != step_begin()) { + OS << " -> "; + } + + switch (S->Kind) { + case SK_ResolveAddressOfOverloadedFunction: + OS << "resolve address of overloaded function"; + break; + + case SK_CastDerivedToBaseRValue: + OS << "derived-to-base case (rvalue" << S->Type.getAsString() << ")"; + break; + + case SK_CastDerivedToBaseLValue: + OS << "derived-to-base case (lvalue" << S->Type.getAsString() << ")"; + break; + + case SK_BindReference: + OS << "bind reference to lvalue"; + break; + + case SK_BindReferenceToTemporary: + OS << "bind reference to a temporary"; + break; + + case SK_UserConversion: + OS << "user-defined conversion via " << S->Function->getNameAsString(); + break; + + case SK_QualificationConversionRValue: + OS << "qualification conversion (rvalue)"; + + case SK_QualificationConversionLValue: + OS << "qualification conversion (lvalue)"; + break; + + case SK_ConversionSequence: + OS << "implicit conversion sequence ("; + S->ICS->DebugPrint(); // FIXME: use OS + OS << ")"; + break; + + case SK_ListInitialization: + OS << "list initialization"; + break; + + case SK_ConstructorInitialization: + OS << "constructor initialization"; + break; + + case SK_ZeroInitialization: + OS << "zero initialization"; + break; + + case SK_CAssignment: + OS << "C assignment"; + break; + + case SK_StringInit: + OS << "string initialization"; + break; + } + } +} + +void InitializationSequence::dump() const { + dump(llvm::errs()); +} + //===----------------------------------------------------------------------===// // Initialization helper functions //===----------------------------------------------------------------------===// diff --git a/lib/Sema/SemaInit.h b/lib/Sema/SemaInit.h index d7d3756..2b49df2 100644 --- a/lib/Sema/SemaInit.h +++ b/lib/Sema/SemaInit.h @@ -15,12 +15,17 @@ #include "SemaOverload.h" #include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" #include "clang/Parse/Action.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallVector.h" #include <cassert> +namespace llvm { + class raw_ostream; +} + namespace clang { class CXXBaseSpecifier; @@ -62,7 +67,6 @@ public: /// \brief The entity being initialized is an element of a vector. /// or vector. EK_VectorElement - }; private: @@ -91,8 +95,8 @@ private: /// base class. CXXBaseSpecifier *Base; - /// \brief When Kind = EK_ArrayOrVectorElement, the index of the - /// array or vector element being initialized. + /// \brief When Kind = EK_ArrayElement or EK_VectorElement, the + /// index of the array or vector element being initialized. unsigned Index; }; @@ -197,6 +201,12 @@ public: /// initialized. DeclaratorDecl *getDecl() const; + /// \brief Retrieve the base specifier. + CXXBaseSpecifier *getBaseSpecifier() const { + assert(getKind() == EK_Base && "Not a base specifier"); + return Base; + } + /// \brief Determine the location of the 'return' keyword when initializing /// the result of a function call. SourceLocation getReturnLoc() const { @@ -440,7 +450,11 @@ public: /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind == /// SK_UserConversion, the function that the expression should be /// resolved to or the conversion function to call, respectively. - FunctionDecl *Function; + /// + /// Always a FunctionDecl. + /// For conversion decls, the naming class is the source type. + /// For construct decls, the naming class is the target type. + DeclAccessPair Function; /// \brief When Kind = SK_ConversionSequence, the implicit conversion /// sequence @@ -607,7 +621,9 @@ public: /// \brief Add a new step invoking a conversion function, which is either /// a constructor or a conversion function. - void AddUserConversionStep(FunctionDecl *Function, QualType T); + void AddUserConversionStep(FunctionDecl *Function, + AccessSpecifier Access, + QualType T); /// \brief Add a new step that performs a qualification conversion to the /// given type. @@ -622,6 +638,7 @@ public: /// \brief Add a constructor-initialization step. void AddConstructorInitializationStep(CXXConstructorDecl *Constructor, + AccessSpecifier Access, QualType T); /// \brief Add a zero-initialization step. @@ -658,6 +675,14 @@ public: assert(getKind() == FailedSequence && "Not an initialization failure!"); return Failure; } + + /// \brief Dump a representation of this initialization sequence to + /// the given stream, for debugging purposes. + void dump(llvm::raw_ostream &OS) const; + + /// \brief Dump a representation of this initialization sequence to + /// standard error, for debugging purposes. + void dump() const; }; } // end namespace clang diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index f5d2a7d..c7569d6 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -404,7 +404,7 @@ void LookupResult::resolveKind() { } void LookupResult::addDeclsFromBasePaths(const CXXBasePaths &P) { - CXXBasePaths::paths_iterator I, E; + CXXBasePaths::const_paths_iterator I, E; DeclContext::lookup_iterator DI, DE; for (I = P.begin(), E = P.end(); I != E; ++I) for (llvm::tie(DI,DE) = I->Decls; DI != DE; ++DI) @@ -438,9 +438,42 @@ void LookupResult::print(llvm::raw_ostream &Out) { } } +/// \brief Lookup a builtin function, when name lookup would otherwise +/// fail. +static bool LookupBuiltin(Sema &S, LookupResult &R) { + Sema::LookupNameKind NameKind = R.getLookupKind(); + + // If we didn't find a use of this identifier, and if the identifier + // corresponds to a compiler builtin, create the decl object for the builtin + // now, injecting it into translation unit scope, and return it. + if (NameKind == Sema::LookupOrdinaryName || + NameKind == Sema::LookupRedeclarationWithLinkage) { + IdentifierInfo *II = R.getLookupName().getAsIdentifierInfo(); + if (II) { + // If this is a builtin on this (or all) targets, create the decl. + if (unsigned BuiltinID = II->getBuiltinID()) { + // In C++, we don't have any predefined library functions like + // 'malloc'. Instead, we'll just error. + if (S.getLangOptions().CPlusPlus && + S.Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + return false; + + NamedDecl *D = S.LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, + S.TUScope, R.isForRedeclaration(), + R.getNameLoc()); + if (D) + R.addDecl(D); + return (D != NULL); + } + } + } + + return false; +} + // 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(LookupResult &R, const DeclContext *DC) { +static bool LookupDirect(Sema &S, LookupResult &R, const DeclContext *DC) { bool Found = false; DeclContext::lookup_const_iterator I, E; @@ -452,87 +485,89 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) { } } + if (!Found && DC->isTranslationUnit() && LookupBuiltin(S, R)) + return true; + if (R.getLookupName().getNameKind() - == DeclarationName::CXXConversionFunctionName && - !R.getLookupName().getCXXNameType()->isDependentType() && - isa<CXXRecordDecl>(DC)) { + != DeclarationName::CXXConversionFunctionName || + R.getLookupName().getCXXNameType()->isDependentType() || + !isa<CXXRecordDecl>(DC)) + return Found; + + // C++ [temp.mem]p6: + // A specialization of a conversion function template is not found by + // name lookup. Instead, any conversion function templates visible in the + // context of the use are considered. [...] + const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); + if (!Record->isDefinition()) + return Found; + + const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions(); + for (UnresolvedSetImpl::iterator U = Unresolved->begin(), + UEnd = Unresolved->end(); U != UEnd; ++U) { + FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U); + if (!ConvTemplate) + continue; + + // When we're performing lookup for the purposes of redeclaration, just + // add the conversion function template. When we deduce template + // arguments for specializations, we'll end up unifying the return + // type of the new declaration with the type of the function template. + if (R.isForRedeclaration()) { + R.addDecl(ConvTemplate); + Found = true; + continue; + } + // C++ [temp.mem]p6: - // A specialization of a conversion function template is not found by - // name lookup. Instead, any conversion function templates visible in the - // context of the use are considered. [...] - const CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); - if (!Record->isDefinition()) - return Found; - - const UnresolvedSetImpl *Unresolved = Record->getConversionFunctions(); - for (UnresolvedSetImpl::iterator U = Unresolved->begin(), - UEnd = Unresolved->end(); U != UEnd; ++U) { - FunctionTemplateDecl *ConvTemplate = dyn_cast<FunctionTemplateDecl>(*U); - if (!ConvTemplate) - continue; - - // When we're performing lookup for the purposes of redeclaration, just - // add the conversion function template. When we deduce template - // arguments for specializations, we'll end up unifying the return - // type of the new declaration with the type of the function template. - if (R.isForRedeclaration()) { - R.addDecl(ConvTemplate); - Found = true; - continue; - } - - // C++ [temp.mem]p6: - // [...] For each such operator, if argument deduction succeeds - // (14.9.2.3), the resulting specialization is used as if found by - // name lookup. - // - // When referencing a conversion function for any purpose other than - // a redeclaration (such that we'll be building an expression with the - // result), perform template argument deduction and place the - // specialization into the result set. We do this to avoid forcing all - // callers to perform special deduction for conversion functions. - Sema::TemplateDeductionInfo Info(R.getSema().Context); - FunctionDecl *Specialization = 0; - - const FunctionProtoType *ConvProto - = ConvTemplate->getTemplatedDecl()->getType() - ->getAs<FunctionProtoType>(); - assert(ConvProto && "Nonsensical conversion function template type"); - - // Compute the type of the function that we would expect the conversion - // function to have, if it were to match the name given. - // FIXME: Calling convention! - QualType ExpectedType - = R.getSema().Context.getFunctionType( - R.getLookupName().getCXXNameType(), - 0, 0, ConvProto->isVariadic(), - ConvProto->getTypeQuals(), - false, false, 0, 0, - ConvProto->getNoReturnAttr()); - - // Perform template argument deduction against the type that we would - // expect the function to have. - if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType, - Specialization, Info) - == Sema::TDK_Success) { - R.addDecl(Specialization); - Found = true; - } + // [...] For each such operator, if argument deduction succeeds + // (14.9.2.3), the resulting specialization is used as if found by + // name lookup. + // + // When referencing a conversion function for any purpose other than + // a redeclaration (such that we'll be building an expression with the + // result), perform template argument deduction and place the + // specialization into the result set. We do this to avoid forcing all + // callers to perform special deduction for conversion functions. + Sema::TemplateDeductionInfo Info(R.getSema().Context, R.getNameLoc()); + FunctionDecl *Specialization = 0; + + const FunctionProtoType *ConvProto + = ConvTemplate->getTemplatedDecl()->getType()->getAs<FunctionProtoType>(); + assert(ConvProto && "Nonsensical conversion function template type"); + + // Compute the type of the function that we would expect the conversion + // function to have, if it were to match the name given. + // FIXME: Calling convention! + QualType ExpectedType + = R.getSema().Context.getFunctionType(R.getLookupName().getCXXNameType(), + 0, 0, ConvProto->isVariadic(), + ConvProto->getTypeQuals(), + false, false, 0, 0, + ConvProto->getNoReturnAttr()); + + // Perform template argument deduction against the type that we would + // expect the function to have. + if (R.getSema().DeduceTemplateArguments(ConvTemplate, 0, ExpectedType, + Specialization, Info) + == Sema::TDK_Success) { + R.addDecl(Specialization); + Found = true; } } - + return Found; } // Performs C++ unqualified lookup into the given file context. static bool -CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS, - UnqualUsingDirectiveSet &UDirs) { +CppNamespaceLookup(Sema &S, LookupResult &R, ASTContext &Context, + DeclContext *NS, UnqualUsingDirectiveSet &UDirs) { assert(NS && NS->isFileContext() && "CppNamespaceLookup() requires namespace!"); // Perform direct name lookup into the LookupCtx. - bool Found = LookupDirect(R, NS); + bool Found = LookupDirect(S, R, NS); // Perform direct name lookup into the namespaces nominated by the // using directives whose common ancestor is this namespace. @@ -540,7 +575,7 @@ CppNamespaceLookup(LookupResult &R, ASTContext &Context, DeclContext *NS, llvm::tie(UI, UEnd) = UDirs.getNamespacesFor(NS); for (; UI != UEnd; ++UI) - if (LookupDirect(R, UI->getNominatedNamespace())) + if (LookupDirect(S, R, UI->getNominatedNamespace())) Found = true; R.resolveKind(); @@ -650,12 +685,9 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { for (; S; S = S->getParent()) { DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); - if (!Ctx || Ctx->isTransparentContext()) + if (Ctx && Ctx->isTransparentContext()) continue; - assert(Ctx && Ctx->isFileContext() && - "We should have been looking only at file context here already."); - // Check whether the IdResolver has anything in this scope. bool Found = false; for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) { @@ -669,16 +701,21 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) { } } - // Look into context considering using-directives. - if (CppNamespaceLookup(R, Context, Ctx, UDirs)) - Found = true; + if (Ctx) { + assert(Ctx->isFileContext() && + "We should have been looking only at file context here already."); + + // Look into context considering using-directives. + if (CppNamespaceLookup(*this, R, Context, Ctx, UDirs)) + Found = true; + } if (Found) { R.resolveKind(); return true; } - if (R.isForRedeclaration() && !Ctx->isTransparentContext()) + if (R.isForRedeclaration() && Ctx && !Ctx->isTransparentContext()) return false; } @@ -793,26 +830,9 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { // If we didn't find a use of this identifier, and if the identifier // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. - if (NameKind == LookupOrdinaryName || - NameKind == LookupRedeclarationWithLinkage) { - IdentifierInfo *II = Name.getAsIdentifierInfo(); - if (II && AllowBuiltinCreation) { - // If this is a builtin on this (or all) targets, create the decl. - if (unsigned BuiltinID = II->getBuiltinID()) { - // In C++, we don't have any predefined library functions like - // 'malloc'. Instead, we'll just error. - if (getLangOptions().CPlusPlus && - Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return false; + if (AllowBuiltinCreation) + return LookupBuiltin(*this, R); - NamedDecl *D = LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID, - S, R.isForRedeclaration(), - R.getNameLoc()); - if (D) R.addDecl(D); - return (D != NULL); - } - } - } return false; } @@ -842,7 +862,7 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) { /// class or enumeration name if and only if the declarations are /// from the same namespace; otherwise (the declarations are from /// different namespaces), the program is ill-formed. -static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, +static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, DeclContext *StartDC) { assert(StartDC->isFileContext() && "start context is not a file context"); @@ -885,7 +905,7 @@ static bool LookupQualifiedNameInUsingDirectives(LookupResult &R, // between LookupResults. bool UseLocal = !R.empty(); LookupResult &DirectR = UseLocal ? LocalR : R; - bool FoundDirect = LookupDirect(DirectR, ND); + bool FoundDirect = LookupDirect(S, DirectR, ND); if (FoundDirect) { // First do any local hiding. @@ -965,7 +985,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, "Declaration context must already be complete!"); // Perform qualified name lookup into the LookupCtx. - if (LookupDirect(R, LookupCtx)) { + if (LookupDirect(*this, R, LookupCtx)) { R.resolveKind(); if (isa<CXXRecordDecl>(LookupCtx)) R.setNamingClass(cast<CXXRecordDecl>(LookupCtx)); @@ -986,7 +1006,7 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, // If this is a namespace, look it up in the implied namespaces. if (LookupCtx->isFileContext()) - return LookupQualifiedNameInUsingDirectives(R, LookupCtx); + return LookupQualifiedNameInUsingDirectives(*this, R, LookupCtx); // If this isn't a C++ class, we aren't allowed to look into base // classes, we're done. @@ -1407,6 +1427,12 @@ addAssociatedClassesAndNamespaces(CXXRecordDecl *Class, AssociatedClasses); } + // Only recurse into base classes for complete types. + if (!Class->hasDefinition()) { + // FIXME: we might need to instantiate templates here + return; + } + // Add direct and indirect base classes along with their associated // namespaces. llvm::SmallVector<CXXRecordDecl *, 32> Bases; @@ -1693,7 +1719,7 @@ ObjCProtocolDecl *Sema::LookupProtocol(IdentifierInfo *II) { void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, - FunctionSet &Functions) { + UnresolvedSetImpl &Functions) { // C++ [over.match.oper]p3: // -- The set of non-member candidates is the result of the // unqualified lookup of operator@ in the context of the @@ -1719,29 +1745,58 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, Op != OpEnd; ++Op) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) { if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) - Functions.insert(FD); // FIXME: canonical FD + Functions.addDecl(FD, Op.getAccess()); // FIXME: canonical FD } else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Op)) { // FIXME: friend operators? // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, // later? if (!FunTmpl->getDeclContext()->isRecord()) - Functions.insert(FunTmpl); + Functions.addDecl(FunTmpl, Op.getAccess()); } } } -static void CollectFunctionDecl(Sema::FunctionSet &Functions, - Decl *D) { - if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) - Functions.insert(Func); - else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) - Functions.insert(FunTmpl); +void ADLResult::insert(NamedDecl *New) { + NamedDecl *&Old = Decls[cast<NamedDecl>(New->getCanonicalDecl())]; + + // If we haven't yet seen a decl for this key, or the last decl + // was exactly this one, we're done. + if (Old == 0 || Old == New) { + Old = New; + return; + } + + // Otherwise, decide which is a more recent redeclaration. + FunctionDecl *OldFD, *NewFD; + if (isa<FunctionTemplateDecl>(New)) { + OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl(); + NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl(); + } else { + OldFD = cast<FunctionDecl>(Old); + NewFD = cast<FunctionDecl>(New); + } + + FunctionDecl *Cursor = NewFD; + while (true) { + Cursor = Cursor->getPreviousDeclaration(); + + // If we got to the end without finding OldFD, OldFD is the newer + // declaration; leave things as they are. + if (!Cursor) return; + + // If we do find OldFD, then NewFD is newer. + if (Cursor == OldFD) break; + + // Otherwise, keep looking. + } + + Old = New; } void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - FunctionSet &Functions) { + ADLResult &Result) { // Find all of the associated namespaces and classes based on the // arguments we have. AssociatedNamespaceSet AssociatedNamespaces; @@ -1784,7 +1839,7 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, // lookup (11.4). DeclContext::lookup_iterator I, E; for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { - Decl *D = *I; + NamedDecl *D = *I; // If the only declaration here is an ordinary friend, consider // it only if it was declared in an associated classes. if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) { @@ -1793,10 +1848,18 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, bool Operator, continue; } - FunctionDecl *Fn; - if (!Operator || !(Fn = dyn_cast<FunctionDecl>(D)) || - IsAcceptableNonMemberOperatorCandidate(Fn, T1, T2, Context)) - CollectFunctionDecl(Functions, D); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); + + if (isa<FunctionDecl>(D)) { + if (Operator && + !IsAcceptableNonMemberOperatorCandidate(cast<FunctionDecl>(D), + T1, T2, Context)) + continue; + } else if (!isa<FunctionTemplateDecl>(D)) + continue; + + Result.insert(D); } } } @@ -1985,6 +2048,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, bool InBaseClass, VisibleDeclConsumer &Consumer, VisibleDeclsRecord &Visited) { + if (!Ctx) + return; + // Make sure we don't visit the same context twice. if (Visited.visitedContext(Ctx->getPrimaryContext())) return; @@ -2022,6 +2088,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result, // Traverse the contexts of inherited C++ classes. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) { + if (!Record->hasDefinition()) + return; + for (CXXRecordDecl::base_class_iterator B = Record->bases_begin(), BEnd = Record->bases_end(); B != BEnd; ++B) { @@ -2138,9 +2207,9 @@ static void LookupVisibleDecls(Scope *S, LookupResult &Result, // For instance methods, look for ivars in the method's interface. LookupResult IvarResult(Result.getSema(), Result.getLookupName(), Result.getNameLoc(), Sema::LookupMemberName); - ObjCInterfaceDecl *IFace = Method->getClassInterface(); - LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, - /*InBaseClass=*/false, Consumer, Visited); + if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) + LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false, + /*InBaseClass=*/false, Consumer, Visited); } // We've already performed all of the name lookup that we need @@ -2312,9 +2381,16 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) { - if (Diags.hasFatalErrorOccurred()) return false; + + // Provide a stop gap for files that are just seriously broken. Trying + // to correct all typos can turn into a HUGE performance penalty, causing + // some files to take minutes to get rejected by the parser. + // FIXME: Is this the right solution? + if (TyposCorrected == 20) + return false; + ++TyposCorrected; // We only attempt to correct typos for identifiers. IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 44a8f15..b79b1cc 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -148,7 +148,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const { // array-to-pointer or function-to-pointer implicit conversions, so // check for their presence as well as checking whether FromType is // a pointer. - if (getToType()->isBooleanType() && + if (getToType(1)->isBooleanType() && (getFromType()->isPointerType() || getFromType()->isBlockPointerType() || First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) return true; @@ -164,7 +164,7 @@ bool StandardConversionSequence:: isPointerConversionToVoidPointer(ASTContext& Context) const { QualType FromType = getFromType(); - QualType ToType = getToType(); + QualType ToType = getToType(1); // Note that FromType has not necessarily been transformed by the // array-to-pointer implicit conversion, so check for its presence @@ -447,16 +447,24 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, bool InOverloadResolution, bool UserCast) { ImplicitConversionSequence ICS; - OverloadCandidateSet Conversions; - OverloadingResult UserDefResult = OR_Success; - if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) + if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) { ICS.setStandard(); - else if (getLangOptions().CPlusPlus && - (UserDefResult = IsUserDefinedConversion(From, ToType, - ICS.UserDefined, - Conversions, - !SuppressUserConversions, AllowExplicit, - ForceRValue, UserCast)) == OR_Success) { + return ICS; + } + + if (!getLangOptions().CPlusPlus) { + ICS.setBad(); + ICS.Bad.init(BadConversionSequence::no_conversion, From, ToType); + return ICS; + } + + OverloadCandidateSet Conversions(From->getExprLoc()); + OverloadingResult UserDefResult + = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions, + !SuppressUserConversions, AllowExplicit, + ForceRValue, UserCast); + + if (UserDefResult == OR_Success) { ICS.setUserDefined(); // C++ [over.ics.user]p4: // A conversion of an expression of class type to the same class @@ -477,7 +485,7 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); ICS.Standard.setFromType(From->getType()); - ICS.Standard.setToType(ToType); + ICS.Standard.setAllToTypes(ToType); ICS.Standard.CopyConstructor = Constructor; if (ToCanon != FromCanon) ICS.Standard.Second = ICK_Derived_To_Base; @@ -595,7 +603,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // conversion (4.4). (C++ 4.2p2) SCS.Second = ICK_Identity; SCS.Third = ICK_Qualification; - SCS.setToType(ToType); + SCS.setAllToTypes(FromType); return true; } } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) { @@ -634,6 +642,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // We don't require any conversions for the first step. SCS.First = ICK_Identity; } + SCS.setToType(0, FromType); // The second conversion can be an integral promotion, floating // point promotion, integral conversion, floating point conversion, @@ -714,6 +723,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // No second conversion required. SCS.Second = ICK_Identity; } + SCS.setToType(1, FromType); QualType CanonFrom; QualType CanonTo; @@ -740,13 +750,13 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, CanonFrom = CanonTo; } } + SCS.setToType(2, FromType); // If we have not converted the argument type to the parameter type, // this is a bad conversion sequence. if (CanonFrom != CanonTo) return false; - SCS.setToType(FromType); return true; } @@ -766,7 +776,8 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // int can represent all the values of the source type; otherwise, // the source rvalue can be converted to an rvalue of type unsigned // int (C++ 4.5p1). - if (FromType->isPromotableIntegerType() && !FromType->isBooleanType()) { + if (FromType->isPromotableIntegerType() && !FromType->isBooleanType() && + !FromType->isEnumeralType()) { if (// We can promote any signed, promotable integer type to an int (FromType->isSignedIntegerType() || // We can promote any unsigned integer type whose size is @@ -1344,14 +1355,13 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, /// CheckMemberPointerConversion - Check the member pointer conversion from the /// expression From to the type ToType. This routine checks for ambiguous or -/// virtual (FIXME: or inaccessible) base-to-derived member pointer conversions +/// virtual or inaccessible base-to-derived member pointer conversions /// for which IsMemberPointerConversion has already returned true. It returns /// true and produces a diagnostic if there was an error, or returns false /// otherwise. bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, CastExpr::CastKind &Kind, bool IgnoreBaseAccess) { - (void)IgnoreBaseAccess; QualType FromType = From->getType(); const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>(); if (!FromPtrType) { @@ -1374,7 +1384,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, assert(FromClass->isRecordType() && "Pointer into non-class."); assert(ToClass->isRecordType() && "Pointer into non-class."); - CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, + CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/ true, /*DetectVirtual=*/true); bool DerivationOkay = IsDerivedFrom(ToClass, FromClass, Paths); assert(DerivationOkay && @@ -1383,13 +1393,6 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, if (Paths.isAmbiguous(Context.getCanonicalType(FromClass). getUnqualifiedType())) { - // Derivation is ambiguous. Redo the check to find the exact paths. - Paths.clear(); - Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(ToClass, FromClass, Paths); - assert(StillOkay && "Derivation changed due to quantum fluctuation."); - (void)StillOkay; - std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); Diag(From->getExprLoc(), diag::err_ambiguous_memptr_conv) << 0 << FromClass << ToClass << PathDisplayStr << From->getSourceRange(); @@ -1403,6 +1406,10 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, return true; } + if (!IgnoreBaseAccess) + CheckBaseClassAccess(From->getExprLoc(), /*BaseToDerived*/ true, + FromClass, ToClass, Paths.front()); + // Must be a base to derived member conversion. Kind = CastExpr::CK_BaseToDerivedMemberPointer; return false; @@ -1418,7 +1425,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { // If FromType and ToType are the same type, this is not a // qualification conversion. - if (FromType == ToType) + if (FromType.getUnqualifiedType() == ToType.getUnqualifiedType()) return false; // (C++ 4.4p4): @@ -1526,13 +1533,16 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) - AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0, + AddTemplateOverloadCandidate(ConstructorTmpl, + ConstructorTmpl->getAccess(), + /*ExplicitArgs*/ 0, &From, 1, CandidateSet, SuppressUserConversions, ForceRValue); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). - AddOverloadCandidate(Constructor, &From, 1, CandidateSet, + AddOverloadCandidate(Constructor, Constructor->getAccess(), + &From, 1, CandidateSet, SuppressUserConversions, ForceRValue); } } @@ -1568,11 +1578,12 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, if (AllowExplicit || !Conv->isExplicit()) { if (ConvTemplate) - AddTemplateConversionCandidate(ConvTemplate, ActingContext, - From, ToType, CandidateSet); + AddTemplateConversionCandidate(ConvTemplate, I.getAccess(), + ActingContext, From, ToType, + CandidateSet); else - AddConversionCandidate(Conv, ActingContext, From, ToType, - CandidateSet); + AddConversionCandidate(Conv, I.getAccess(), ActingContext, + From, ToType, CandidateSet); } } } @@ -1601,7 +1612,7 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, User.After.setAsIdentityConversion(); User.After.setFromType( ThisType->getAs<PointerType>()->getPointeeType()); - User.After.setToType(ToType); + User.After.setAllToTypes(ToType); return OR_Success; } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { @@ -1647,7 +1658,7 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, bool Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { ImplicitConversionSequence ICS; - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(From->getExprLoc()); OverloadingResult OvResult = IsUserDefinedConversion(From, ToType, ICS.UserDefined, CandidateSet, true, false, false); @@ -1718,6 +1729,43 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, return ImplicitConversionSequence::Indistinguishable; } +// 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 +compareStandardConversionSubsets(ASTContext &Context, + const StandardConversionSequence& SCS1, + const StandardConversionSequence& SCS2) { + ImplicitConversionSequence::CompareKind Result + = ImplicitConversionSequence::Indistinguishable; + + if (SCS1.Second != SCS2.Second) { + if (SCS1.Second == ICK_Identity) + Result = ImplicitConversionSequence::Better; + else if (SCS2.Second == ICK_Identity) + Result = ImplicitConversionSequence::Worse; + else + return ImplicitConversionSequence::Indistinguishable; + } else if (!Context.hasSameType(SCS1.getToType(1), SCS2.getToType(1))) + return ImplicitConversionSequence::Indistinguishable; + + if (SCS1.Third == SCS2.Third) { + return Context.hasSameType(SCS1.getToType(2), SCS2.getToType(2))? Result + : ImplicitConversionSequence::Indistinguishable; + } + + if (SCS1.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Worse + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Better; + + if (SCS2.Third == ICK_Identity) + return Result == ImplicitConversionSequence::Better + ? ImplicitConversionSequence::Indistinguishable + : ImplicitConversionSequence::Worse; + + return ImplicitConversionSequence::Indistinguishable; +} + /// CompareStandardConversionSequences - Compare two standard /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). @@ -1733,21 +1781,9 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // excluding any Lvalue Transformation; the identity conversion // sequence is considered to be a subsequence of any // non-identity conversion sequence) or, if not that, - if (SCS1.Second == SCS2.Second && SCS1.Third == SCS2.Third) - // Neither is a proper subsequence of the other. Do nothing. - ; - else if ((SCS1.Second == ICK_Identity && SCS1.Third == SCS2.Third) || - (SCS1.Third == ICK_Identity && SCS1.Second == SCS2.Second) || - (SCS1.Second == ICK_Identity && - SCS1.Third == ICK_Identity)) - // SCS1 is a proper subsequence of SCS2. - return ImplicitConversionSequence::Better; - else if ((SCS2.Second == ICK_Identity && SCS2.Third == SCS1.Third) || - (SCS2.Third == ICK_Identity && SCS2.Second == SCS1.Second) || - (SCS2.Second == ICK_Identity && - SCS2.Third == ICK_Identity)) - // SCS2 is a proper subsequence of SCS1. - return ImplicitConversionSequence::Worse; + if (ImplicitConversionSequence::CompareKind CK + = compareStandardConversionSubsets(Context, SCS1, SCS2)) + return CK; // -- the rank of S1 is better than the rank of S2 (by the rules // defined below), or, if not that, @@ -1852,8 +1888,8 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1, // top-level cv-qualifiers, and the type to which the reference // initialized by S2 refers is more cv-qualified than the type // to which the reference initialized by S1 refers. - QualType T1 = SCS1.getToType(); - QualType T2 = SCS2.getToType(); + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); T1 = Context.getCanonicalType(T1); T2 = Context.getCanonicalType(T2); Qualifiers T1Quals, T2Quals; @@ -1894,8 +1930,8 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1, // FIXME: the example in the standard doesn't use a qualification // conversion (!) - QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr); - QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr); + QualType T1 = SCS1.getToType(2); + QualType T2 = SCS2.getToType(2); T1 = Context.getCanonicalType(T1); T2 = Context.getCanonicalType(T2); Qualifiers T1Quals, T2Quals; @@ -1984,9 +2020,9 @@ ImplicitConversionSequence::CompareKind Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2) { QualType FromType1 = SCS1.getFromType(); - QualType ToType1 = SCS1.getToType(); + QualType ToType1 = SCS1.getToType(1); QualType FromType2 = SCS2.getFromType(); - QualType ToType2 = SCS2.getToType(); + QualType ToType2 = SCS2.getToType(1); // Adjust the types we're converting from via the array-to-pointer // conversion, if we need to. @@ -2276,7 +2312,7 @@ Sema::TryObjectArgumentInitialization(QualType OrigFromType, // Success. Mark this as a reference binding. ICS.setStandard(); ICS.Standard.setFromType(FromType); - ICS.Standard.setToType(ImplicitParamType); + ICS.Standard.setAllToTypes(ImplicitParamType); ICS.Standard.ReferenceBinding = true; ICS.Standard.DirectBinding = true; ICS.Standard.RRefBinding = false; @@ -2360,6 +2396,7 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { /// code completion. void Sema::AddOverloadCandidate(FunctionDecl *Function, + AccessSpecifier Access, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, @@ -2380,7 +2417,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // function, e.g., X::f(). We use an empty type for the implied // object argument (C++ [over.call.func]p3), and the acting context // is irrelevant. - AddMethodCandidate(Method, Method->getParent(), + AddMethodCandidate(Method, Access, Method->getParent(), QualType(), Args, NumArgs, CandidateSet, SuppressUserConversions, ForceRValue); return; @@ -2410,6 +2447,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = Function; + Candidate.Access = Access; Candidate.Viable = true; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; @@ -2469,35 +2507,33 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, /// \brief Add all of the function declarations in the given function set to /// the overload canddiate set. -void Sema::AddFunctionCandidates(const FunctionSet &Functions, +void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { - for (FunctionSet::const_iterator F = Functions.begin(), - FEnd = Functions.end(); - F != FEnd; ++F) { + for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { // FIXME: using declarations if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) { if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) - AddMethodCandidate(cast<CXXMethodDecl>(FD), + AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getAccess(), cast<CXXMethodDecl>(FD)->getParent(), Args[0]->getType(), Args + 1, NumArgs - 1, CandidateSet, SuppressUserConversions); else - AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet, SuppressUserConversions); } else { FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*F); if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) - AddMethodTemplateCandidate(FunTmpl, + AddMethodTemplateCandidate(FunTmpl, F.getAccess(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), /*FIXME: explicit args */ 0, Args[0]->getType(), Args + 1, NumArgs - 1, CandidateSet, SuppressUserConversions); else - AddTemplateOverloadCandidate(FunTmpl, + AddTemplateOverloadCandidate(FunTmpl, AS_none, /*FIXME: explicit args */ 0, Args, NumArgs, CandidateSet, SuppressUserConversions); @@ -2508,6 +2544,7 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, /// AddMethodCandidate - Adds a named decl (which is some kind of /// method) as a method candidate to the given overload set. void Sema::AddMethodCandidate(NamedDecl *Decl, + AccessSpecifier Access, QualType ObjectType, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -2520,13 +2557,13 @@ void Sema::AddMethodCandidate(NamedDecl *Decl, if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) { assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) && "Expected a member function template"); - AddMethodTemplateCandidate(TD, ActingContext, /*ExplicitArgs*/ 0, + AddMethodTemplateCandidate(TD, Access, ActingContext, /*ExplicitArgs*/ 0, ObjectType, Args, NumArgs, CandidateSet, SuppressUserConversions, ForceRValue); } else { - AddMethodCandidate(cast<CXXMethodDecl>(Decl), ActingContext, + AddMethodCandidate(cast<CXXMethodDecl>(Decl), Access, ActingContext, ObjectType, Args, NumArgs, CandidateSet, SuppressUserConversions, ForceRValue); } @@ -2542,8 +2579,9 @@ void Sema::AddMethodCandidate(NamedDecl *Decl, /// a slightly hacky way to implement the overloading rules for elidable copy /// initialization in C++0x (C++0x 12.8p15). void -Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext, - QualType ObjectType, Expr **Args, unsigned NumArgs, +Sema::AddMethodCandidate(CXXMethodDecl *Method, AccessSpecifier Access, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, bool ForceRValue) { const FunctionProtoType* Proto @@ -2562,6 +2600,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext, CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = Method; + Candidate.Access = Access; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; @@ -2639,6 +2678,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext, /// function template specialization. void Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + AccessSpecifier Access, CXXRecordDecl *ActingContext, const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, @@ -2658,7 +2698,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, // functions. In such a case, the candidate functions generated from each // function template are combined with the set of non-template candidate // functions. - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, @@ -2674,8 +2714,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, assert(Specialization && "Missing member function template specialization?"); assert(isa<CXXMethodDecl>(Specialization) && "Specialization is not a member function?"); - AddMethodCandidate(cast<CXXMethodDecl>(Specialization), ActingContext, - ObjectType, Args, NumArgs, + AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Access, + ActingContext, ObjectType, Args, NumArgs, CandidateSet, SuppressUserConversions, ForceRValue); } @@ -2684,6 +2724,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, /// an appropriate function template specialization. void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + AccessSpecifier Access, const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, @@ -2701,29 +2742,30 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // functions. In such a case, the candidate functions generated from each // function template are combined with the set of non-template candidate // functions. - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, NumArgs, Specialization, Info)) { - // FIXME: Record what happened with template argument deduction, so - // that we can give the user a beautiful diagnostic. - (void) Result; - CandidateSet.push_back(OverloadCandidate()); OverloadCandidate &Candidate = CandidateSet.back(); Candidate.Function = FunctionTemplate->getTemplatedDecl(); + Candidate.Access = Access; Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + + // TODO: record more information about failed template arguments + Candidate.DeductionFailure.Result = Result; + Candidate.DeductionFailure.TemplateParameter = Info.Param.getOpaqueValue(); return; } // Add the function template specialization produced by template argument // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddOverloadCandidate(Specialization, Args, NumArgs, CandidateSet, + AddOverloadCandidate(Specialization, Access, Args, NumArgs, CandidateSet, SuppressUserConversions, ForceRValue); } @@ -2735,6 +2777,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, /// conversion function produces). void Sema::AddConversionCandidate(CXXConversionDecl *Conversion, + AccessSpecifier Access, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet& CandidateSet) { @@ -2751,11 +2794,12 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = Conversion; + Candidate.Access = Access; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.FinalConversion.setAsIdentityConversion(); Candidate.FinalConversion.setFromType(Conversion->getConversionType()); - Candidate.FinalConversion.setToType(ToType); + Candidate.FinalConversion.setAllToTypes(ToType); // Determine the implicit conversion sequence for the implicit // object parameter. @@ -2837,6 +2881,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, /// [temp.deduct.conv]). void Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, + AccessSpecifier Access, CXXRecordDecl *ActingDC, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet) { @@ -2846,7 +2891,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, CandidateSet.getLocation()); CXXConversionDecl *Specialization = 0; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ToType, @@ -2860,7 +2905,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, // Add the conversion function template specialization produced by // template argument deduction as a candidate. assert(Specialization && "Missing function template specialization?"); - AddConversionCandidate(Specialization, ActingDC, From, ToType, CandidateSet); + AddConversionCandidate(Specialization, Access, ActingDC, From, ToType, + CandidateSet); } /// AddSurrogateCandidate - Adds a "surrogate" candidate function that @@ -2869,6 +2915,7 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, /// with the given arguments (C++ [over.call.object]p2-4). Proto is /// the type of function that we'll eventually be calling. void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, + AccessSpecifier Access, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, QualType ObjectType, @@ -2883,6 +2930,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = 0; + Candidate.Access = Access; Candidate.Surrogate = Conversion; Candidate.Viable = true; Candidate.IsSurrogate = true; @@ -2968,7 +3016,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, SourceRange OpRange) { - FunctionSet Functions; + UnresolvedSet<16> Fns; QualType T1 = Args[0]->getType(); QualType T2; @@ -2977,9 +3025,10 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S, DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(Op); if (S) - LookupOverloadedOperatorName(Op, S, T1, T2, Functions); - ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, Functions); - AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet); + LookupOverloadedOperatorName(Op, S, T1, T2, Fns); + AddFunctionCandidates(Fns, Args, NumArgs, CandidateSet, false); + AddArgumentDependentLookupCandidates(OpName, false, Args, NumArgs, 0, + CandidateSet); AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange); AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet); } @@ -3029,7 +3078,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, OperEnd = Operators.end(); Oper != OperEnd; ++Oper) - AddMethodCandidate(*Oper, Args[0]->getType(), + AddMethodCandidate(*Oper, Oper.getAccess(), Args[0]->getType(), Args + 1, NumArgs - 1, CandidateSet, /* SuppressUserConversions = */ false); } @@ -3055,6 +3104,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); Candidate.Function = 0; + Candidate.Access = AS_none; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.BuiltinTypes.ResultTy = ResultTy; @@ -3362,6 +3412,9 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { } CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); + if (!ClassDecl->hasDefinition()) + return VRQuals; + const UnresolvedSetImpl *Conversions = ClassDecl->getVisibleConversionFunctions(); @@ -4108,54 +4161,45 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, /// candidate set (C++ [basic.lookup.argdep]). void Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, + bool Operator, Expr **Args, unsigned NumArgs, const TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, bool PartialOverloading) { - FunctionSet Functions; + ADLResult Fns; - // FIXME: Should we be trafficking in canonical function decls throughout? - - // Record all of the function candidates that we've already - // added to the overload set, so that we don't add those same - // candidates a second time. - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), - CandEnd = CandidateSet.end(); - Cand != CandEnd; ++Cand) - if (Cand->Function) { - Functions.insert(Cand->Function); - if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) - Functions.insert(FunTmpl); - } + // FIXME: This approach for uniquing ADL results (and removing + // redundant candidates from the set) relies on pointer-equality, + // which means we need to key off the canonical decl. However, + // always going back to the canonical decl might not get us the + // right set of default arguments. What default arguments are + // we supposed to consider on ADL candidates, anyway? // FIXME: Pass in the explicit template arguments? - ArgumentDependentLookup(Name, /*Operator*/false, Args, NumArgs, Functions); + ArgumentDependentLookup(Name, Operator, Args, NumArgs, Fns); // Erase all of the candidates we already knew about. - // FIXME: This is suboptimal. Is there a better way? for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) if (Cand->Function) { - Functions.erase(Cand->Function); + Fns.erase(Cand->Function); if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) - Functions.erase(FunTmpl); + Fns.erase(FunTmpl); } // For each of the ADL candidates we found, add it to the overload // set. - for (FunctionSet::iterator Func = Functions.begin(), - FuncEnd = Functions.end(); - Func != FuncEnd; ++Func) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) { + for (ADLResult::iterator I = Fns.begin(), E = Fns.end(); I != E; ++I) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { if (ExplicitTemplateArgs) continue; - AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + AddOverloadCandidate(FD, AS_none, Args, NumArgs, CandidateSet, false, false, PartialOverloading); } else - AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), - ExplicitTemplateArgs, + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), + AS_none, ExplicitTemplateArgs, Args, NumArgs, CandidateSet); } } @@ -4164,7 +4208,8 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, /// candidate is a better candidate than the second (C++ 13.3.3p1). bool Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2) { + const OverloadCandidate& Cand2, + SourceLocation Loc) { // Define viable functions to be better candidates than non-viable // functions. if (!Cand2.Viable) @@ -4227,6 +4272,7 @@ Sema::isBetterOverloadCandidate(const OverloadCandidate& Cand1, if (FunctionTemplateDecl *BetterTemplate = getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), Cand2.Function->getPrimaryTemplate(), + Loc, isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion : TPOC_Call)) return BetterTemplate == Cand1.Function->getPrimaryTemplate(); @@ -4279,7 +4325,8 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(); Cand != CandidateSet.end(); ++Cand) { if (Cand->Viable) { - if (Best == CandidateSet.end() || isBetterOverloadCandidate(*Cand, *Best)) + if (Best == CandidateSet.end() || + isBetterOverloadCandidate(*Cand, *Best, Loc)) Best = Cand; } } @@ -4294,7 +4341,7 @@ OverloadingResult Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, Cand != CandidateSet.end(); ++Cand) { if (Cand->Viable && Cand != Best && - !isBetterOverloadCandidate(*Best, *Cand)) { + !isBetterOverloadCandidate(*Best, *Cand, Loc)) { Best = CandidateSet.end(); return OR_Ambiguous; } @@ -4414,6 +4461,20 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { QualType FromTy = Conv.Bad.getFromType(); QualType ToTy = Conv.Bad.getToType(); + if (FromTy == S.Context.OverloadTy) { + assert(FromExpr); + Expr *E = FromExpr->IgnoreParens(); + if (isa<UnaryOperator>(E)) + E = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); + DeclarationName Name = cast<OverloadExpr>(E)->getName(); + + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload) + << (unsigned) FnKind << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << ToTy << Name << I+1; + return; + } + // Do some hand-waving analysis to see if the non-viability is due // to a qualifier mismatch. CanQualType CFromTy = S.Context.getCanonicalType(FromTy); @@ -4520,6 +4581,58 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, << (unsigned) FnKind << Description << mode << modeCount << NumFormalArgs; } +/// Diagnose a failed template-argument deduction. +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, + Expr **Args, unsigned NumArgs) { + FunctionDecl *Fn = Cand->Function; // pattern + + TemplateParameter Param = TemplateParameter::getFromOpaqueValue( + Cand->DeductionFailure.TemplateParameter); + + switch (Cand->DeductionFailure.Result) { + case Sema::TDK_Success: + llvm_unreachable("TDK_success while diagnosing bad deduction"); + + case Sema::TDK_Incomplete: { + NamedDecl *ParamD; + (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) || + (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) || + (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>()); + assert(ParamD && "no parameter found for incomplete deduction result"); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + return; + } + + // TODO: diagnose these individually, then kill off + // note_ovl_candidate_bad_deduction, which is uselessly vague. + case Sema::TDK_InstantiationDepth: + case Sema::TDK_Inconsistent: + case Sema::TDK_InconsistentQuals: + case Sema::TDK_SubstitutionFailure: + case Sema::TDK_NonDeducedMismatch: + case Sema::TDK_TooManyArguments: + case Sema::TDK_TooFewArguments: + case Sema::TDK_InvalidExplicitArguments: + case Sema::TDK_FailedOverloadResolution: + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + return; + } +} + +/// Generates a 'note' diagnostic for an overload candidate. We've +/// already generated a primary error at the call site. +/// +/// It really does need to be a single diagnostic with its caret +/// pointed at the candidate declaration. Yes, this creates some +/// major challenges of technical writing. Yes, this makes pointing +/// out problems with specific arguments quite awkward. It's still +/// better than generating twenty screens of text for every failed +/// overload. +/// +/// It would be great to be able to express per-candidate problems +/// more richly for those diagnostic clients that cared, but we'd +/// still have to be just as careful with the default diagnostics. void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, Expr **Args, unsigned NumArgs) { FunctionDecl *Fn = Cand->Function; @@ -4546,6 +4659,8 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, return DiagnoseArityMismatch(S, Cand, NumArgs); case ovl_fail_bad_deduction: + return DiagnoseBadDeduction(S, Cand, Args, NumArgs); + case ovl_fail_trivial_conversion: case ovl_fail_bad_final_conversion: return S.NoteOverloadCandidate(Fn); @@ -4651,8 +4766,8 @@ struct CompareOverloadCandidatesForDisplay { // TODO: introduce a tri-valued comparison for overload // candidates. Would be more worthwhile if we had a sort // that could exploit it. - if (S.isBetterOverloadCandidate(*L, *R)) return true; - if (S.isBetterOverloadCandidate(*R, *L)) return false; + if (S.isBetterOverloadCandidate(*L, *R, SourceLocation())) return true; + if (S.isBetterOverloadCandidate(*R, *L, SourceLocation())) return false; } else if (R->Viable) return false; @@ -4842,6 +4957,14 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, } } +static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, NamedDecl *D, + AccessSpecifier AS) { + if (isa<UnresolvedLookupExpr>(E)) + return S.CheckUnresolvedLookupAccess(cast<UnresolvedLookupExpr>(E), D, AS); + + return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D, AS); +} + /// ResolveAddressOfOverloadedFunction - Try to resolve the address of /// an overloaded function (C++ [over.over]), where @p From is an /// expression with overloaded function type and @p ToType is the type @@ -4878,52 +5001,28 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, return 0; // Find the actual overloaded function declaration. + if (From->getType() != Context.OverloadTy) + return 0; // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] - Expr *OvlExpr = From->IgnoreParens(); - // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) { - if (UnOp->getOpcode() == UnaryOperator::AddrOf) - OvlExpr = UnOp->getSubExpr()->IgnoreParens(); + OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer(); + TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0; + if (OvlExpr->hasExplicitTemplateArgs()) { + OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer); + ExplicitTemplateArgs = &ETABuffer; } - bool HasExplicitTemplateArgs = false; - TemplateArgumentListInfo ExplicitTemplateArgs; - - llvm::SmallVector<NamedDecl*,8> Fns; - - // Look into the overloaded expression. - if (UnresolvedLookupExpr *UL - = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) { - Fns.append(UL->decls_begin(), UL->decls_end()); - if (UL->hasExplicitTemplateArgs()) { - HasExplicitTemplateArgs = true; - UL->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - } else if (UnresolvedMemberExpr *ME - = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) { - Fns.append(ME->decls_begin(), ME->decls_end()); - if (ME->hasExplicitTemplateArgs()) { - HasExplicitTemplateArgs = true; - ME->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - } - - // If we didn't actually find anything, we're done. - if (Fns.empty()) - return 0; - // Look through all of the overloaded functions, searching for one // whose type matches exactly. - llvm::SmallPtrSet<FunctionDecl *, 4> Matches; + UnresolvedSet<4> Matches; // contains only FunctionDecls bool FoundNonTemplateFunction = false; - for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(), - E = Fns.end(); I != E; ++I) { + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + E = OvlExpr->decls_end(); I != E; ++I) { // Look through any using declarations to find the underlying function. NamedDecl *Fn = (*I)->getUnderlyingDecl(); @@ -4953,10 +5052,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // overloaded functions considered. // FIXME: We don't really want to build the specialization here, do we? FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, - (HasExplicitTemplateArgs ? &ExplicitTemplateArgs : 0), + = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, FunctionType, Specialization, Info)) { // FIXME: make a note of the failed deduction for diagnostics. (void)Result; @@ -4965,8 +5063,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // a candidate? Find a testcase before changing the code. assert(FunctionType == Context.getCanonicalType(Specialization->getType())); - Matches.insert( - cast<FunctionDecl>(Specialization->getCanonicalDecl())); + Matches.addDecl(cast<FunctionDecl>(Specialization->getCanonicalDecl()), + I.getAccess()); } continue; @@ -4979,7 +5077,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, continue; // If we have explicit template arguments, skip non-templates. - if (HasExplicitTemplateArgs) + if (OvlExpr->hasExplicitTemplateArgs()) continue; } else if (IsMember) continue; @@ -4989,7 +5087,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) || IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, ResultTy)) { - Matches.insert(cast<FunctionDecl>(FunDecl->getCanonicalDecl())); + Matches.addDecl(cast<FunctionDecl>(FunDecl->getCanonicalDecl()), + I.getAccess()); FoundNonTemplateFunction = true; } } @@ -4999,14 +5098,15 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, if (Matches.empty()) return 0; else if (Matches.size() == 1) { - FunctionDecl *Result = *Matches.begin(); + FunctionDecl *Result = cast<FunctionDecl>(*Matches.begin()); MarkDeclarationReferenced(From->getLocStart(), Result); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, Result, Matches.begin().getAccess()); return Result; } // C++ [over.over]p4: // If more than one function is selected, [...] - typedef llvm::SmallPtrSet<FunctionDecl *, 4>::iterator MatchIter; if (!FoundNonTemplateFunction) { // [...] and any given function template specialization F1 is // eliminated if the set contains a second function template @@ -5018,41 +5118,50 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, // two-pass algorithm (similar to the one used to identify the // best viable function in an overload set) that identifies the // best function template (if it exists). - llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(), - Matches.end()); - FunctionDecl *Result = - getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(), + + UnresolvedSetIterator Result = + getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, From->getLocStart(), PDiag(), PDiag(diag::err_addr_ovl_ambiguous) - << TemplateMatches[0]->getDeclName(), + << Matches[0]->getDeclName(), PDiag(diag::note_ovl_candidate) << (unsigned) oc_function_template); - MarkDeclarationReferenced(From->getLocStart(), Result); - return Result; + assert(Result != Matches.end() && "no most-specialized template"); + MarkDeclarationReferenced(From->getLocStart(), *Result); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, *Result, Result.getAccess()); + return cast<FunctionDecl>(*Result); } // [...] any function template specializations in the set are // eliminated if the set also contains a non-template function, [...] - llvm::SmallVector<FunctionDecl *, 4> RemainingMatches; - for (MatchIter M = Matches.begin(), MEnd = Matches.end(); M != MEnd; ++M) - if ((*M)->getPrimaryTemplate() == 0) - RemainingMatches.push_back(*M); + for (unsigned I = 0, N = Matches.size(); I != N; ) { + if (cast<FunctionDecl>(Matches[I].getDecl())->getPrimaryTemplate() == 0) + ++I; + else { + Matches.erase(I); + --N; + } + } // [...] After such eliminations, if any, there shall remain exactly one // selected function. - if (RemainingMatches.size() == 1) { - FunctionDecl *Result = RemainingMatches.front(); - MarkDeclarationReferenced(From->getLocStart(), Result); - return Result; + if (Matches.size() == 1) { + UnresolvedSetIterator Match = Matches.begin(); + MarkDeclarationReferenced(From->getLocStart(), *Match); + if (Complain) + CheckUnresolvedAccess(*this, OvlExpr, *Match, Match.getAccess()); + return cast<FunctionDecl>(*Match); } // FIXME: We should probably return the same thing that BestViableFunction // returns (even if we issue the diagnostics here). Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << RemainingMatches[0]->getDeclName(); - for (unsigned I = 0, N = RemainingMatches.size(); I != N; ++I) - NoteOverloadCandidate(RemainingMatches[I]); + << Matches[0]->getDeclName(); + for (UnresolvedSetIterator I = Matches.begin(), + E = Matches.end(); I != E; ++I) + NoteOverloadCandidate(cast<FunctionDecl>(*I)); return 0; } @@ -5067,47 +5176,27 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] - Expr *OvlExpr = From->IgnoreParens(); - // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(OvlExpr)) { - if (UnOp->getOpcode() == UnaryOperator::AddrOf) - OvlExpr = UnOp->getSubExpr()->IgnoreParens(); - } - - bool HasExplicitTemplateArgs = false; - TemplateArgumentListInfo ExplicitTemplateArgs; - - llvm::SmallVector<NamedDecl*,8> Fns; - - // Look into the overloaded expression. - if (UnresolvedLookupExpr *UL - = dyn_cast<UnresolvedLookupExpr>(OvlExpr)) { - Fns.append(UL->decls_begin(), UL->decls_end()); - if (UL->hasExplicitTemplateArgs()) { - HasExplicitTemplateArgs = true; - UL->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - } else if (UnresolvedMemberExpr *ME - = dyn_cast<UnresolvedMemberExpr>(OvlExpr)) { - Fns.append(ME->decls_begin(), ME->decls_end()); - if (ME->hasExplicitTemplateArgs()) { - HasExplicitTemplateArgs = true; - ME->copyTemplateArgumentsInto(ExplicitTemplateArgs); - } - } + + if (From->getType() != Context.OverloadTy) + return 0; + + OverloadExpr *OvlExpr = OverloadExpr::find(From).getPointer(); // If we didn't actually find any template-ids, we're done. - if (Fns.empty() || !HasExplicitTemplateArgs) + if (!OvlExpr->hasExplicitTemplateArgs()) return 0; + + TemplateArgumentListInfo ExplicitTemplateArgs; + OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); // Look through all of the overloaded functions, searching for one // whose type matches exactly. FunctionDecl *Matched = 0; - for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Fns.begin(), - E = Fns.end(); I != E; ++I) { + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + E = OvlExpr->decls_end(); I != E; ++I) { // C++0x [temp.arg.explicit]p3: // [...] In contexts where deduction is done and fails, or in contexts // where deduction is not done, if a template argument list is @@ -5123,7 +5212,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info)) { @@ -5145,6 +5234,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, NamedDecl *Callee, + AccessSpecifier Access, const TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet &CandidateSet, @@ -5154,14 +5244,14 @@ static void AddOverloadedCallCandidate(Sema &S, if (FunctionDecl *Func = dyn_cast<FunctionDecl>(Callee)) { assert(!ExplicitTemplateArgs && "Explicit template arguments?"); - S.AddOverloadCandidate(Func, Args, NumArgs, CandidateSet, false, false, - PartialOverloading); + S.AddOverloadCandidate(Func, Access, Args, NumArgs, CandidateSet, + false, false, PartialOverloading); return; } if (FunctionTemplateDecl *FuncTemplate = dyn_cast<FunctionTemplateDecl>(Callee)) { - S.AddTemplateOverloadCandidate(FuncTemplate, ExplicitTemplateArgs, + S.AddTemplateOverloadCandidate(FuncTemplate, Access, ExplicitTemplateArgs, Args, NumArgs, CandidateSet); return; } @@ -5217,12 +5307,13 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) - AddOverloadedCallCandidate(*this, *I, ExplicitTemplateArgs, + AddOverloadedCallCandidate(*this, *I, I.getAccess(), ExplicitTemplateArgs, Args, NumArgs, CandidateSet, PartialOverloading); if (ULE->requiresADL()) - AddArgumentDependentLookupCandidates(ULE->getName(), Args, NumArgs, + AddArgumentDependentLookupCandidates(ULE->getName(), /*Operator*/ false, + Args, NumArgs, ExplicitTemplateArgs, CandidateSet, PartialOverloading); @@ -5321,7 +5412,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, } #endif - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(Fn->getExprLoc()); // Add the functions denoted by the callee to the set of candidate // functions, including those from argument-dependent lookup. @@ -5338,6 +5429,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, switch (BestViableFunction(CandidateSet, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; + CheckUnresolvedLookupAccess(ULE, FDecl, Best->getAccess()); Fn = FixOverloadedFunctionReference(Fn, FDecl); return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); } @@ -5372,7 +5464,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE, return ExprError(); } -static bool IsOverloaded(const Sema::FunctionSet &Functions) { +static bool IsOverloaded(const UnresolvedSetImpl &Functions) { return Functions.size() > 1 || (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); } @@ -5393,10 +5485,10 @@ static bool IsOverloaded(const Sema::FunctionSet &Functions) { /// by CreateOverloadedUnaryOp(). /// /// \param input The input argument. -Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, - unsigned OpcIn, - FunctionSet &Functions, - ExprArg input) { +Sema::OwningExprResult +Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, + const UnresolvedSetImpl &Fns, + ExprArg input) { UnaryOperator::Opcode Opc = static_cast<UnaryOperator::Opcode>(OpcIn); Expr *Input = (Expr *)input.get(); @@ -5418,14 +5510,12 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, } if (Input->isTypeDependent()) { + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, OpLoc, - /*ADL*/ true, IsOverloaded(Functions)); - for (FunctionSet::iterator Func = Functions.begin(), - FuncEnd = Functions.end(); - Func != FuncEnd; ++Func) - Fn->addDecl(*Func); + /*ADL*/ true, IsOverloaded(Fns)); + Fn->addDecls(Fns.begin(), Fns.end()); input.release(); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, @@ -5435,14 +5525,20 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, } // Build an empty overload set. - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(OpLoc); // Add the candidates from the given function set. - AddFunctionCandidates(Functions, &Args[0], NumArgs, CandidateSet, false); + AddFunctionCandidates(Fns, &Args[0], NumArgs, CandidateSet, false); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + Args, NumArgs, + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet); @@ -5459,6 +5555,8 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { + CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); + if (PerformObjectArgumentInitialization(Input, Method)) return ExprError(); } else { @@ -5555,7 +5653,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, Sema::OwningExprResult Sema::CreateOverloadedBinOp(SourceLocation OpLoc, unsigned OpcIn, - FunctionSet &Functions, + const UnresolvedSetImpl &Fns, Expr *LHS, Expr *RHS) { Expr *Args[2] = { LHS, RHS }; LHS=RHS=0; //Please use only Args instead of LHS/RHS couple @@ -5567,7 +5665,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // If either side is type-dependent, create an appropriate dependent // expression. if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { - if (Functions.empty()) { + if (Fns.empty()) { // If there are no functions to store, just build a dependent // BinaryOperator or CompoundAssignment. if (Opc <= BinaryOperator::Assign || Opc > BinaryOperator::OrAssign) @@ -5580,17 +5678,15 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, Context.DependentTy, OpLoc)); } - + + // FIXME: save results of ADL from here? + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, OpLoc, - /* ADL */ true, IsOverloaded(Functions)); - - for (FunctionSet::iterator Func = Functions.begin(), - FuncEnd = Functions.end(); - Func != FuncEnd; ++Func) - Fn->addDecl(*Func); + /*ADL*/ true, IsOverloaded(Fns)); + Fn->addDecls(Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, 2, Context.DependentTy, @@ -5612,14 +5708,20 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); // Build an empty overload set. - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(OpLoc); // Add the candidates from the given function set. - AddFunctionCandidates(Functions, Args, 2, CandidateSet, false); + AddFunctionCandidates(Fns, Args, 2, CandidateSet, false); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); + // Add candidates from ADL. + AddArgumentDependentLookupCandidates(OpName, /*Operator*/ true, + Args, 2, + /*ExplicitTemplateArgs*/ 0, + CandidateSet); + // Add builtin operator candidates. AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet); @@ -5636,6 +5738,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Convert the arguments. if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) { + // Best->Access is only meaningful for class members. + CheckMemberOperatorAccess(OpLoc, Args[0], Method, Best->getAccess()); + OwningExprResult Arg1 = PerformCopyInitialization( InitializedEntity::InitializeParameter( @@ -5770,8 +5875,9 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // expression. if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, + = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, 0, SourceRange(), OpName, LLoc, /*ADL*/ true, /*Overloaded*/ false); // Can't add any actual overloads yet @@ -5785,7 +5891,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, } // Build an empty overload set. - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(LLoc); // Subscript can only be overloaded as a member function. @@ -5806,14 +5912,24 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched an overloaded operator. Build a call to that // operator. + CheckMemberOperatorAccess(LLoc, Args[0], FnDecl, Best->getAccess()); + // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], Method) || - PerformCopyInitialization(Args[1], - FnDecl->getParamDecl(0)->getType(), - AA_Passing)) + if (PerformObjectArgumentInitialization(Args[0], Method)) return ExprError(); + // Convert the arguments. + OwningExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + FnDecl->getParamDecl(0)), + SourceLocation(), + Owned(Args[1])); + if (InputInit.isInvalid()) + return ExprError(); + + Args[1] = InputInit.takeAs<Expr>(); + // Determine the result type QualType ResultTy = FnDecl->getType()->getAs<FunctionType>()->getResultType(); @@ -5914,7 +6030,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, QualType ObjectType = UnresExpr->getBaseType(); // Add overload candidates - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc()); // FIXME: avoid copy. TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = 0; @@ -5937,11 +6053,12 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (TemplateArgs) continue; - AddMethodCandidate(Method, ActingDC, ObjectType, Args, NumArgs, + AddMethodCandidate(Method, I.getAccess(), ActingDC, ObjectType, + Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/false); } else { AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), - ActingDC, TemplateArgs, + I.getAccess(), ActingDC, TemplateArgs, ObjectType, Args, NumArgs, CandidateSet, /*SuppressUsedConversions=*/false); @@ -5954,6 +6071,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, switch (BestViableFunction(CandidateSet, UnresExpr->getLocStart(), Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); + CheckUnresolvedMemberAccess(UnresExpr, Method, Best->getAccess()); break; case OR_No_Viable_Function: @@ -6043,7 +6161,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // operators of T. The function call operators of T are obtained by // ordinary lookup of the name operator() in the context of // (E).operator(). - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(LParenLoc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); if (RequireCompleteType(LParenLoc, Object->getType(), @@ -6057,7 +6175,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { - AddMethodCandidate(*Oper, Object->getType(), Args, NumArgs, CandidateSet, + AddMethodCandidate(*Oper, Oper.getAccess(), Object->getType(), + Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/ false); } @@ -6101,7 +6220,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, ConvType = ConvPtrType->getPointeeType(); if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) - AddSurrogateCandidate(Conv, ActingContext, Proto, + AddSurrogateCandidate(Conv, I.getAccess(), ActingContext, Proto, Object->getType(), Args, NumArgs, CandidateSet); } @@ -6158,6 +6277,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, = cast<CXXConversionDecl>( Best->Conversions[0].UserDefined.ConversionFunction); + CheckMemberOperatorAccess(LParenLoc, Object, Conv, Best->getAccess()); + // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion // on the object argument, then let ActOnCallExpr finish the job. @@ -6171,6 +6292,9 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, CommaLocs, RParenLoc).release(); } + CheckMemberOperatorAccess(LParenLoc, Object, + Best->Function, Best->getAccess()); + // We found an overloaded operator(). Build a CXXOperatorCallExpr // that calls this method, using Object for the implicit object // parameter and passing along the remaining arguments. @@ -6232,8 +6356,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, Arg = Args[i]; // Pass the argument. - QualType ProtoArgType = Proto->getArgType(i); - IsError |= PerformCopyInitialization(Arg, ProtoArgType, AA_Passing); + + OwningExprResult InputInit + = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Method->getParamDecl(i)), + SourceLocation(), Owned(Arg)); + + IsError |= InputInit.isInvalid(); + Arg = InputInit.takeAs<Expr>(); } else { OwningExprResult DefArg = BuildCXXDefaultArgExpr(LParenLoc, Method, Method->getParamDecl(i)); @@ -6274,6 +6404,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { Expr *Base = static_cast<Expr *>(BaseIn.get()); assert(Base->getType()->isRecordType() && "left-hand side must have class type"); + SourceLocation Loc = Base->getExprLoc(); + // C++ [over.ref]p1: // // [...] An expression x->m is interpreted as (x.operator->())->m @@ -6281,10 +6413,10 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { // the operator is selected as the best match function by the // overload resolution mechanism (13.3). DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow); - OverloadCandidateSet CandidateSet; + OverloadCandidateSet CandidateSet(Loc); const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); - if (RequireCompleteType(Base->getLocStart(), Base->getType(), + if (RequireCompleteType(Loc, Base->getType(), PDiag(diag::err_typecheck_incomplete_tag) << Base->getSourceRange())) return ExprError(); @@ -6300,7 +6432,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) { if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - AddMethodCandidate(cast<CXXMethodDecl>(D), ActingContext, + AddMethodCandidate(cast<CXXMethodDecl>(D), Oper.getAccess(), ActingContext, Base->getType(), 0, 0, CandidateSet, /*SuppressUserConversions=*/false); } diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index f8353e3..e6dfa74 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -139,9 +139,10 @@ namespace clang { /// QualType. void *FromTypePtr; - /// ToType - The type that this conversion is converting to. This - /// is an opaque pointer that can be translated into a QualType. - void *ToTypePtr; + /// ToType - The types that this conversion is converting to in + /// each step. This is an opaque pointer that can be translated + /// into a QualType. + void *ToTypePtrs[3]; /// CopyConstructor - The copy constructor that is used to perform /// this conversion, when the conversion is actually just the @@ -151,12 +152,22 @@ namespace clang { CXXConstructorDecl *CopyConstructor; void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } - void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); } + void setToType(unsigned Idx, QualType T) { + assert(Idx < 3 && "To type index is out of range"); + ToTypePtrs[Idx] = T.getAsOpaquePtr(); + } + void setAllToTypes(QualType T) { + ToTypePtrs[0] = T.getAsOpaquePtr(); + ToTypePtrs[1] = ToTypePtrs[0]; + ToTypePtrs[2] = ToTypePtrs[0]; + } + QualType getFromType() const { return QualType::getFromOpaquePtr(FromTypePtr); } - QualType getToType() const { - return QualType::getFromOpaquePtr(ToTypePtr); + QualType getToType(unsigned Idx) const { + assert(Idx < 3 && "To type index is out of range"); + return QualType::getFromOpaquePtr(ToTypePtrs[Idx]); } void setAsIdentityConversion(); @@ -446,11 +457,33 @@ namespace clang { /// Actually an OverloadFailureKind. unsigned char FailureKind; - /// FinalConversion - For a conversion function (where Function is - /// a CXXConversionDecl), the standard conversion that occurs - /// after the call to the overload candidate to convert the result - /// of calling the conversion function to the required type. - StandardConversionSequence FinalConversion; + /// PathAccess - The 'path access' to the given function/conversion. + /// Actually an AccessSpecifier. + unsigned Access; + + AccessSpecifier getAccess() const { + return AccessSpecifier(Access); + } + + /// A structure used to record information about a failed + /// template argument deduction. + struct DeductionFailureInfo { + // A Sema::TemplateDeductionResult. + unsigned Result; + + // A TemplateParameter. + void *TemplateParameter; + }; + + union { + DeductionFailureInfo DeductionFailure; + + /// FinalConversion - For a conversion function (where Function is + /// a CXXConversionDecl), the standard conversion that occurs + /// after the call to the overload candidate to convert the result + /// of calling the conversion function to the required type. + StandardConversionSequence FinalConversion; + }; /// hasAmbiguousConversion - Returns whether this overload /// candidate requires an ambiguous conversion or not. @@ -468,8 +501,13 @@ namespace clang { class OverloadCandidateSet : public llvm::SmallVector<OverloadCandidate, 16> { typedef llvm::SmallVector<OverloadCandidate, 16> inherited; llvm::SmallPtrSet<Decl *, 16> Functions; - + + SourceLocation Loc; public: + OverloadCandidateSet(SourceLocation Loc) : Loc(Loc) {} + + SourceLocation getLocation() const { return Loc; } + /// \brief Determine when this overload candidate will be new to the /// overload set. bool isNewCandidate(Decl *F) { diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 0c207fa..fa42634 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -93,6 +93,15 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) { if (isa<ObjCImplicitSetterGetterRefExpr>(E)) DiagID = diag::warn_unused_property_expr; + 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 the callee has attribute pure, const, or warn_unused_result, warn with // a more specific message to make it clear what is happening. @@ -370,6 +379,22 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs, return false; } +/// CmpEnumVals - Comparison predicate for sorting enumeration values. +/// +static bool CmpEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first < rhs.first; +} + +/// EqEnumVals - Comparison preficate for uniqing enumeration values. +/// +static bool EqEnumVals(const std::pair<llvm::APSInt, EnumConstantDecl*>& lhs, + const std::pair<llvm::APSInt, EnumConstantDecl*>& rhs) +{ + return lhs.first == rhs.first; +} + /// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of /// potentially integral-promoted expression @p expr. static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { @@ -482,6 +507,16 @@ static bool CheckCXXSwitchCondition(Sema &S, SourceLocation SwitchLoc, return false; } +/// ActOnSwitchBodyError - This is called if there is an error parsing the +/// body of the switch stmt instead of ActOnFinishSwitchStmt. +void Sema::ActOnSwitchBodyError(SourceLocation SwitchLoc, StmtArg Switch, + StmtArg Body) { + // Keep the switch stack balanced. + assert(getSwitchStack().back() == (SwitchStmt*)Switch.get() && + "switch stack missing push/pop!"); + getSwitchStack().pop_back(); +} + Action::OwningStmtResult Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, StmtArg Body) { @@ -550,7 +585,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, CaseValsTy CaseVals; // Keep track of any GNU case ranges we see. The APSInt is the low value. - std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRanges; + typedef std::vector<std::pair<llvm::APSInt, CaseStmt*> > CaseRangesTy; + CaseRangesTy CaseRanges; DefaultStmt *TheDefaultStmt = 0; @@ -713,6 +749,75 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch, } } } + + // Check to see if switch is over an Enum and handles all of its + // values + const EnumType* ET = dyn_cast<EnumType>(CondTypeBeforePromotion); + // If switch has default case, then ignore it. + if (!CaseListIsErroneous && !TheDefaultStmt && ET) { + const EnumDecl *ED = ET->getDecl(); + typedef llvm::SmallVector<std::pair<llvm::APSInt, EnumConstantDecl*>, 64> EnumValsTy; + EnumValsTy EnumVals; + + // Gather all enum values, set their type and sort them, allowing easier comparison + // with CaseVals. + for (EnumDecl::enumerator_iterator EDI = ED->enumerator_begin(); EDI != ED->enumerator_end(); EDI++) { + llvm::APSInt Val = (*EDI)->getInitVal(); + if(Val.getBitWidth() < CondWidth) + Val.extend(CondWidth); + Val.setIsSigned(CondIsSigned); + EnumVals.push_back(std::make_pair(Val, (*EDI))); + } + std::stable_sort(EnumVals.begin(), EnumVals.end(), CmpEnumVals); + EnumValsTy::iterator EIend = std::unique(EnumVals.begin(), EnumVals.end(), EqEnumVals); + // See which case values aren't in enum + EnumValsTy::const_iterator EI = EnumVals.begin(); + for (CaseValsTy::const_iterator CI = CaseVals.begin(); CI != CaseVals.end(); CI++) { + while (EI != EIend && EI->first < CI->first) + EI++; + if (EI == EIend || EI->first > CI->first) + Diag(CI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + // See which of case ranges aren't in enum + EI = EnumVals.begin(); + for (CaseRangesTy::const_iterator RI = CaseRanges.begin(); RI != CaseRanges.end() && EI != EIend; RI++) { + while (EI != EIend && EI->first < RI->first) + EI++; + + if (EI == EIend || EI->first != RI->first) { + Diag(RI->second->getLHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + while (EI != EIend && EI->first < Hi) + EI++; + if (EI == EIend || EI->first != Hi) + Diag(RI->second->getRHS()->getExprLoc(), diag::not_in_enum) << ED->getDeclName(); + } + //Check which enum vals aren't in switch + CaseValsTy::const_iterator CI = CaseVals.begin(); + CaseRangesTy::const_iterator RI = CaseRanges.begin(); + EI = EnumVals.begin(); + for (; EI != EIend; EI++) { + //Drop unneeded case values + llvm::APSInt CIVal; + while (CI != CaseVals.end() && CI->first < EI->first) + CI++; + + if (CI != CaseVals.end() && CI->first == EI->first) + continue; + + //Drop unneeded case ranges + for (; RI != CaseRanges.end(); RI++) { + llvm::APSInt Hi = RI->second->getRHS()->EvaluateAsInt(Context); + if (EI->first <= Hi) + break; + } + + if (RI == CaseRanges.end() || EI->first < RI->first) + Diag(CondExpr->getExprLoc(), diag::warn_missing_cases) << EI->second->getDeclName(); + } + } } // FIXME: If the case list was broken is some way, we don't have a good system @@ -863,7 +968,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, << FirstType << First->getSourceRange(); } if (Second) { - DefaultFunctionArrayConversion(Second); + DefaultFunctionArrayLvalueConversion(Second); QualType SecondType = Second->getType(); if (!SecondType->isObjCObjectPointerType()) Diag(ForLoc, diag::err_collection_expr_type) @@ -896,10 +1001,10 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr* E = DestExp.takeAs<Expr>(); if (!E->isTypeDependent()) { QualType ETy = E->getType(); + QualType DestTy = Context.getPointerType(Context.VoidTy.withConst()); AssignConvertType ConvTy = - CheckSingleAssignmentConstraints(Context.VoidPtrTy, E); - if (DiagnoseAssignmentResult(ConvTy, StarLoc, Context.VoidPtrTy, ETy, - E, AA_Passing)) + CheckSingleAssignmentConstraints(DestTy, E); + if (DiagnoseAssignmentResult(ConvTy, StarLoc, DestTy, ETy, E, AA_Passing)) return StmtError(); } return Owned(new (Context) IndirectGotoStmt(GotoLoc, StarLoc, E)); @@ -937,7 +1042,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { if (RetValExp) { // Don't call UsualUnaryConversions(), since we don't want to do // integer promotions here. - DefaultFunctionArrayConversion(RetValExp); + DefaultFunctionArrayLvalueConversion(RetValExp); CurBlock->ReturnType = RetValExp->getType(); if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(RetValExp)) { // We have to remove a 'const' added to copied-in variable which was @@ -981,11 +1086,19 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // In C++ the return statement is handled via a copy initialization. // the C version of which boils down to CheckSingleAssignmentConstraints. - // FIXME: Leaks RetValExp. - if (PerformCopyInitialization(RetValExp, FnRetType, AA_Returning)) + OwningExprResult Res = PerformCopyInitialization( + InitializedEntity::InitializeResult(ReturnLoc, + FnRetType), + SourceLocation(), + Owned(RetValExp)); + if (Res.isInvalid()) { + // FIXME: Cleanup temporaries here, anyway? return StmtError(); - - if (RetValExp) CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); + } + + RetValExp = Res.takeAs<Expr>(); + if (RetValExp) + CheckReturnStackAddr(RetValExp, FnRetType, ReturnLoc); } return Owned(new (Context) ReturnStmt(ReturnLoc, RetValExp)); @@ -1025,7 +1138,8 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { QualType FnRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - if (FD->hasAttr<NoReturnAttr>()) + if (FD->hasAttr<NoReturnAttr>() || + FD->getType()->getAs<FunctionType>()->getNoReturnAttr()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) @@ -1121,6 +1235,10 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, ExprArg rex) { /// This method checks to see if the argument is an acceptable l-value and /// returns false if it is a case we can handle. static bool CheckAsmLValue(const Expr *E, Sema &S) { + // Type dependent expressions will be checked during instantiation. + if (E->isTypeDependent()) + return false; + if (E->isLvalue(S.Context) == Expr::LV_Valid) return false; // Cool, this is an lvalue. @@ -1148,7 +1266,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, - std::string *Names, + IdentifierInfo **Names, MultiExprArg constraints, MultiExprArg exprs, ExprArg asmString, @@ -1175,9 +1293,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - TargetInfo::ConstraintInfo Info(Literal->getStrData(), - Literal->getByteLength(), - Names[i]); + llvm::StringRef OutputName; + if (Names[i]) + OutputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); if (!Context.Target.validateOutputConstraint(Info)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_invalid_output_constraint) @@ -1202,9 +1322,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - TargetInfo::ConstraintInfo Info(Literal->getStrData(), - Literal->getByteLength(), - Names[i]); + llvm::StringRef InputName; + if (Names[i]) + InputName = Names[i]->getName(); + + TargetInfo::ConstraintInfo Info(Literal->getString(), InputName); if (!Context.Target.validateInputConstraint(OutputConstraintInfos.data(), NumOutputs, Info)) { return StmtError(Diag(Literal->getLocStart(), @@ -1232,7 +1354,7 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, } } - DefaultFunctionArrayConversion(Exprs[i]); + DefaultFunctionArrayLvalueConversion(Exprs[i]); InputConstraintInfos.push_back(Info); } @@ -1244,11 +1366,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, return StmtError(Diag(Literal->getLocStart(),diag::err_asm_wide_character) << Literal->getSourceRange()); - std::string Clobber(Literal->getStrData(), - Literal->getStrData() + - Literal->getByteLength()); + llvm::StringRef Clobber = Literal->getString(); - if (!Context.Target.isValidGCCRegisterName(Clobber.c_str())) + if (!Context.Target.isValidGCCRegisterName(Clobber)) return StmtError(Diag(Literal->getLocStart(), diag::err_asm_unknown_register_name) << Clobber); } @@ -1258,9 +1378,9 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc, asmString.release(); clobbers.release(); AsmStmt *NS = - new (Context) AsmStmt(AsmLoc, IsSimple, IsVolatile, MSAsm, NumOutputs, - NumInputs, Names, Constraints, Exprs, AsmString, - NumClobbers, Clobbers, RParenLoc); + new (Context) AsmStmt(Context, AsmLoc, IsSimple, IsVolatile, MSAsm, + NumOutputs, NumInputs, Names, Constraints, Exprs, + AsmString, NumClobbers, Clobbers, RParenLoc); // Validate the asm string, ensuring it makes sense given the operands we // have. llvm::SmallVector<AsmStmt::AsmStringPiece, 8> Pieces; @@ -1527,7 +1647,7 @@ Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock, CurFunctionNeedsScopeChecking = true; RawHandlers.release(); - return Owned(new (Context) CXXTryStmt(TryLoc, - static_cast<Stmt*>(TryBlock.release()), - Handlers, NumHandlers)); + return Owned(CXXTryStmt::Create(Context, TryLoc, + static_cast<Stmt*>(TryBlock.release()), + Handlers, NumHandlers)); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 0040156..10e411f 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -823,7 +823,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // Check for redefinition of this class template. if (TUK == TUK_Definition) { - if (TagDecl *Def = PrevRecordDecl->getDefinition(Context)) { + if (TagDecl *Def = PrevRecordDecl->getDefinition()) { Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); // FIXME: Would it make sense to try to "forget" the previous @@ -1235,18 +1235,14 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // such a member, the member declaration shall be preceded by a // template<> for each enclosing class template that is // explicitly specialized. - // We interpret this as forbidding typedefs of template - // specializations in the scope specifiers of out-of-line decls. - if (const TypedefType *TT = dyn_cast<TypedefType>(T)) { - const Type *UnderlyingT = TT->LookThroughTypedefs().getTypePtr(); - if (isa<TemplateSpecializationType>(UnderlyingT)) - // FIXME: better source location information. - Diag(DeclStartLoc, diag::err_typedef_in_def_scope) << QualType(T,0); - T = UnderlyingT; - } + // + // Following the existing practice of GNU and EDG, we allow a typedef of a + // template specialization type. + if (const TypedefType *TT = dyn_cast<TypedefType>(T)) + T = TT->LookThroughTypedefs().getTypePtr(); if (const TemplateSpecializationType *SpecType - = dyn_cast<TemplateSpecializationType>(T)) { + = dyn_cast<TemplateSpecializationType>(T)) { TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl(); if (!Template) continue; // FIXME: should this be an error? probably... @@ -1525,17 +1521,19 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); QualifierRange = SS.getRange(); } + + // We don't want lookup warnings at this point. + R.suppressDiagnostics(); bool Dependent = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), &TemplateArgs); UnresolvedLookupExpr *ULE - = UnresolvedLookupExpr::Create(Context, Dependent, + = UnresolvedLookupExpr::Create(Context, Dependent, R.getNamingClass(), Qualifier, QualifierRange, R.getLookupName(), R.getNameLoc(), RequiresADL, TemplateArgs); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) - ULE->addDecl(*I); + ULE->addDecls(R.begin(), R.end()); return Owned(ULE); } @@ -2305,7 +2303,17 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, } else DRE = dyn_cast<DeclRefExpr>(Arg); - if (!DRE || !isa<ValueDecl>(DRE->getDecl())) + if (!DRE) + return Diag(Arg->getSourceRange().getBegin(), + diag::err_template_arg_not_decl_ref) + << Arg->getSourceRange(); + + // Stop checking the precise nature of the argument if it is value dependent, + // it should be checked when instantiated. + if (Arg->isValueDependent()) + return false; + + if (!isa<ValueDecl>(DRE->getDecl())) return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_object_or_func_form) << Arg->getSourceRange(); @@ -2324,7 +2332,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // Functions must have external linkage. if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (Func->getLinkage() != NamedDecl::ExternalLinkage) { + if (!isExternalLinkage(Func->getLinkage())) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_function_not_extern) << Func << Arg->getSourceRange(); @@ -2339,7 +2347,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, } if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (Var->getLinkage() != NamedDecl::ExternalLinkage) { + if (!isExternalLinkage(Var->getLinkage())) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_object_not_extern) << Var << Arg->getSourceRange(); @@ -2656,9 +2664,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - if (Entity) - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); + if (Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + } else { + if (Entity) + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); + Converted = TemplateArgument(Entity); + } return false; } @@ -2696,9 +2708,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - if (Entity) - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); + if (Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + } else { + if (Entity) + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); + Converted = TemplateArgument(Entity); + } return false; } @@ -2712,7 +2728,8 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, assert(ParamRefType->getPointeeType()->isObjectType() && "Only object references allowed here"); - if (!Context.hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) { + QualType ReferredType = ParamRefType->getPointeeType(); + if (!Context.hasSameUnqualifiedType(ReferredType, ArgType)) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_no_ref_bind) << InstantiatedParamType << Arg->getType() @@ -2722,7 +2739,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } unsigned ParamQuals - = Context.getCanonicalType(ParamType).getCVRQualifiers(); + = Context.getCanonicalType(ReferredType).getCVRQualifiers(); unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers(); if ((ParamQuals | ArgQuals) != ParamQuals) { @@ -2738,8 +2755,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); - Converted = TemplateArgument(Entity); + if (Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + } else { + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); + Converted = TemplateArgument(Entity); + } return false; } @@ -3375,12 +3396,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // FIXME: Diagnose friend partial specializations - // FIXME: Template parameter list matters, too - ClassTemplatePartialSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); - } else + if (!Name.isDependent() && + !TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs.getArgumentArray(), + TemplateArgs.size())) { + Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) + << ClassTemplate->getDeclName(); + isPartialSpecialization = false; + } else { + // FIXME: Template parameter list matters, too + ClassTemplatePartialSpecializationDecl::Profile(ID, + Converted.getFlatArguments(), + Converted.flatSize(), + Context); + } + } + + if (!isPartialSpecialization) ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), Converted.flatSize(), @@ -3410,7 +3442,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, QualType CanonType; if (PrevDecl && (PrevDecl->getSpecializationKind() == TSK_Undeclared || - TUK == TUK_Friend)) { + TUK == TUK_Friend)) { // Since the only prior class template specialization with these // arguments was referenced but not declared, or we're only // referencing this specialization as a friend, reuse that @@ -3423,8 +3455,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } else if (isPartialSpecialization) { // Build the canonical type that describes the converted template // arguments of the class template partial specialization. - CanonType = Context.getTemplateSpecializationType( - TemplateName(ClassTemplate), + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType(CanonTemplate, Converted.getFlatArguments(), Converted.flatSize()); @@ -3532,7 +3564,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Check that this isn't a redefinition of this specialization. if (TUK == TUK_Definition) { - if (RecordDecl *Def = Specialization->getDefinition(Context)) { + if (RecordDecl *Def = Specialization->getDefinition()) { SourceRange Range(TemplateNameLoc, RAngleLoc); Diag(TemplateNameLoc, diag::err_redefinition) << Context.getTypeDeclType(Specialization) << Range; @@ -3619,6 +3651,16 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, return DeclPtrTy(); } +/// \brief Strips various properties off an implicit instantiation +/// that has just been explicitly specialized. +static void StripImplicitInstantiation(NamedDecl *D) { + D->invalidateAttrs(); + + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + FD->setInlineSpecified(false); + } +} + /// \brief Diagnose cases where we have an explicit template specialization /// before/after an explicit template instantiation, producing diagnostics /// for those cases where they are required and determining whether the @@ -3669,6 +3711,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, if (PrevPointOfInstantiation.isInvalid()) { // The declaration itself has not actually been instantiated, so it is // still okay to specialize it. + StripImplicitInstantiation(PrevDecl); return false; } // Fall through @@ -3817,8 +3860,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. - typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet; - CandidateSet Candidates; + UnresolvedSet<8> Candidates; DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -3837,7 +3879,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Perform template argument deduction to determine whether we may be // specializing this template. // FIXME: It is somewhat wasteful to build - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, FD->getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, @@ -3851,22 +3893,24 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, } // Record this candidate. - Candidates.push_back(Specialization); + Candidates.addDecl(Specialization, I.getAccess()); } } // Find the most specialized function template. - FunctionDecl *Specialization = getMostSpecialized(Candidates.data(), - Candidates.size(), - TPOC_Other, - FD->getLocation(), + UnresolvedSetIterator Result + = getMostSpecialized(Candidates.begin(), Candidates.end(), + TPOC_Other, FD->getLocation(), PartialDiagnostic(diag::err_function_template_spec_no_match) << FD->getDeclName(), PartialDiagnostic(diag::err_function_template_spec_ambiguous) << FD->getDeclName() << (ExplicitTemplateArgs != 0), PartialDiagnostic(diag::note_function_template_spec_matched)); - if (!Specialization) + if (Result == Candidates.end()) return true; + + // Ignore access information; it doesn't figure into redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); // FIXME: Check if the prior specialization has a point of instantiation. // If so, we have run afoul of . @@ -3887,15 +3931,15 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, FunctionTemplateSpecializationInfo *SpecInfo = Specialization->getTemplateSpecializationInfo(); assert(SpecInfo && "Function template specialization info missing?"); - if (SpecInfo->getPointOfInstantiation().isValid()) { - Diag(FD->getLocation(), diag::err_specialization_after_instantiation) - << FD; - Diag(SpecInfo->getPointOfInstantiation(), - diag::note_instantiation_required_here) - << (Specialization->getTemplateSpecializationKind() - != TSK_ImplicitInstantiation); + + bool SuppressNew = false; + if (CheckSpecializationInstantiationRedecl(FD->getLocation(), + TSK_ExplicitSpecialization, + Specialization, + SpecInfo->getTemplateSpecializationKind(), + SpecInfo->getPointOfInstantiation(), + SuppressNew)) return true; - } // Mark the prior declaration as an explicit specialization, so that later // clients know that this is an explicit specialization. @@ -3904,8 +3948,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, // Turn the given function declaration into a function template // specialization, with the template arguments from the previous // specialization. - FD->setFunctionTemplateSpecialization(Context, - Specialization->getPrimaryTemplate(), + FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), new (Context) TemplateArgumentList( *Specialization->getTemplateSpecializationArgs()), /*InsertPos=*/0, @@ -3997,14 +4040,15 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. assert(MSInfo && "Member specialization info missing?"); - if (MSInfo->getPointOfInstantiation().isValid()) { - Diag(Member->getLocation(), diag::err_specialization_after_instantiation) - << Member; - Diag(MSInfo->getPointOfInstantiation(), - diag::note_instantiation_required_here) - << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation); + + bool SuppressNew = false; + if (CheckSpecializationInstantiationRedecl(Member->getLocation(), + TSK_ExplicitSpecialization, + Instantiation, + MSInfo->getTemplateSpecializationKind(), + MSInfo->getPointOfInstantiation(), + SuppressNew)) return true; - } // Check the scope of this explicit specialization. if (CheckTemplateSpecializationScope(*this, @@ -4288,13 +4332,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, // instantiation. ClassTemplateSpecializationDecl *Def = cast_or_null<ClassTemplateSpecializationDecl>( - Specialization->getDefinition(Context)); + Specialization->getDefinition()); if (!Def) InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK); // Instantiate the members of this class template specialization. Def = cast_or_null<ClassTemplateSpecializationDecl>( - Specialization->getDefinition(Context)); + Specialization->getDefinition()); if (Def) InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); @@ -4371,7 +4415,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Verify that it is okay to explicitly instantiate here. CXXRecordDecl *PrevDecl = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration()); - if (!PrevDecl && Record->getDefinition(Context)) + if (!PrevDecl && Record->getDefinition()) PrevDecl = Record; if (PrevDecl) { MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); @@ -4388,13 +4432,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, } CXXRecordDecl *RecordDef - = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); + = cast_or_null<CXXRecordDecl>(Record->getDefinition()); if (!RecordDef) { // C++ [temp.explicit]p3: // A definition of a member class of a class template shall be in scope // at the point of an explicit instantiation of the member class. CXXRecordDecl *Def - = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); + = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); if (!Def) { Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member) << 0 << Record->getDeclName() << Record->getDeclContext(); @@ -4407,7 +4451,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, TSK)) return true; - RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); + RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition()); if (!RecordDef) return true; } @@ -4568,7 +4612,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // A member function [...] of a class template can be explicitly // instantiated from the member definition associated with its class // template. - llvm::SmallVector<FunctionDecl *, 8> Matches; + UnresolvedSet<8> Matches; for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; @@ -4577,7 +4621,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (Context.hasSameUnqualifiedType(Method->getType(), R)) { Matches.clear(); - Matches.push_back(Method); + Matches.addDecl(Method, P.getAccess()); if (Method->getTemplateSpecializationKind() == TSK_Undeclared) break; } @@ -4588,7 +4632,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, D.getIdentifierLoc()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, @@ -4599,19 +4643,22 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, continue; } - Matches.push_back(Specialization); + Matches.addDecl(Specialization, P.getAccess()); } // Find the most specialized function template specialization. - FunctionDecl *Specialization - = getMostSpecialized(Matches.data(), Matches.size(), TPOC_Other, + UnresolvedSetIterator Result + = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, D.getIdentifierLoc(), PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name, PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name, PartialDiagnostic(diag::note_explicit_instantiation_candidate)); - if (!Specialization) + if (Result == Matches.end()) return true; + + // Ignore access control bits, we don't need them for redeclaration checking. + FunctionDecl *Specialization = cast<FunctionDecl>(*Result); if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) { Diag(D.getIdentifierLoc(), diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 7b433e9..df4d4a8 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -49,7 +49,7 @@ namespace clang { using namespace clang; static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument &Param, const TemplateArgument &Arg, @@ -72,7 +72,7 @@ static NonTypeTemplateParmDecl *getDeducedParameterFromExpr(Expr *E) { /// \brief Deduce the value of the given non-type template parameter /// from the given constant. static Sema::TemplateDeductionResult -DeduceNonTypeTemplateArgument(ASTContext &Context, +DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, llvm::APSInt Value, Sema::TemplateDeductionInfo &Info, @@ -84,7 +84,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, QualType T = NTTP->getType(); // FIXME: Make sure we didn't overflow our data type! - unsigned AllowedBits = Context.getTypeSize(T); + unsigned AllowedBits = S.Context.getTypeSize(T); if (Value.getBitWidth() != AllowedBits) Value.extOrTrunc(AllowedBits); Value.setIsSigned(T->isSignedIntegerType()); @@ -126,7 +126,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, /// /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult -DeduceNonTypeTemplateArgument(ASTContext &Context, +DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Expr *Value, Sema::TemplateDeductionInfo &Info, @@ -152,8 +152,8 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, if (Deduced[NTTP->getIndex()].getKind() == TemplateArgument::Expression) { // Compare the expressions for equality llvm::FoldingSetNodeID ID1, ID2; - Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, Context, true); - Value->Profile(ID2, Context, true); + Deduced[NTTP->getIndex()].getAsExpr()->Profile(ID1, S.Context, true); + Value->Profile(ID2, S.Context, true); if (ID1 == ID2) return Sema::TDK_Success; @@ -169,7 +169,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, /// /// \returns true if deduction succeeded, false otherwise. static Sema::TemplateDeductionResult -DeduceNonTypeTemplateArgument(ASTContext &Context, +DeduceNonTypeTemplateArgument(Sema &S, NonTypeTemplateParmDecl *NTTP, Decl *D, Sema::TemplateDeductionInfo &Info, @@ -202,7 +202,7 @@ DeduceNonTypeTemplateArgument(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, TemplateName Param, TemplateName Arg, @@ -221,13 +221,13 @@ DeduceTemplateArguments(ASTContext &Context, TemplateArgument &ExistingArg = Deduced[TempParam->getIndex()]; if (ExistingArg.isNull()) { // This is the first deduction for this template template parameter. - ExistingArg = TemplateArgument(Context.getCanonicalTemplateName(Arg)); + ExistingArg = TemplateArgument(S.Context.getCanonicalTemplateName(Arg)); return Sema::TDK_Success; } // Verify that the previous binding matches this deduction. assert(ExistingArg.getKind() == TemplateArgument::Template); - if (Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg)) + if (S.Context.hasSameTemplateName(ExistingArg.getAsTemplate(), Arg)) return Sema::TDK_Success; // Inconsistent deduction. @@ -238,7 +238,7 @@ DeduceTemplateArguments(ASTContext &Context, } // Verify that the two template names are equivalent. - if (Context.hasSameTemplateName(Param, Arg)) + if (S.Context.hasSameTemplateName(Param, Arg)) return Sema::TDK_Success; // Mismatch of non-dependent template parameter to argument. @@ -250,7 +250,7 @@ DeduceTemplateArguments(ASTContext &Context, /// \brief Deduce the template arguments by comparing the template parameter /// type (which is a template-id) with the template argument type. /// -/// \param Context the AST context in which this deduction occurs. +/// \param S the Sema /// /// \param TemplateParams the template parameters that we are deducing /// @@ -266,7 +266,7 @@ DeduceTemplateArguments(ASTContext &Context, /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateSpecializationType *Param, QualType Arg, @@ -279,7 +279,7 @@ DeduceTemplateArguments(ASTContext &Context, = dyn_cast<TemplateSpecializationType>(Arg)) { // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, Param->getTemplateName(), SpecArg->getTemplateName(), Info, Deduced)) @@ -291,7 +291,7 @@ DeduceTemplateArguments(ASTContext &Context, unsigned NumArgs = std::min(SpecArg->getNumArgs(), Param->getNumArgs()); for (unsigned I = 0; I != NumArgs; ++I) if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, Param->getArg(I), SpecArg->getArg(I), Info, Deduced)) @@ -314,7 +314,7 @@ DeduceTemplateArguments(ASTContext &Context, // Perform template argument deduction for the template name. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, + = DeduceTemplateArguments(S, TemplateParams, Param->getTemplateName(), TemplateName(SpecArg->getSpecializedTemplate()), @@ -328,7 +328,7 @@ DeduceTemplateArguments(ASTContext &Context, for (unsigned I = 0; I != NumArgs; ++I) if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, Param->getArg(I), ArgArgs.get(I), Info, Deduced)) @@ -340,7 +340,7 @@ DeduceTemplateArguments(ASTContext &Context, /// \brief Deduce the template arguments by comparing the parameter type and /// the argument type (C++ [temp.deduct.type]). /// -/// \param Context the AST context in which this deduction occurs. +/// \param S the semantic analysis object within which we are deducing /// /// \param TemplateParams the template parameters that we are deducing /// @@ -359,7 +359,7 @@ DeduceTemplateArguments(ASTContext &Context, /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, QualType ArgIn, Sema::TemplateDeductionInfo &Info, @@ -367,8 +367,8 @@ DeduceTemplateArguments(ASTContext &Context, unsigned TDF) { // We only want to look at the canonical types, since typedefs and // sugar are not part of template argument deduction. - QualType Param = Context.getCanonicalType(ParamIn); - QualType Arg = Context.getCanonicalType(ArgIn); + QualType Param = S.Context.getCanonicalType(ParamIn); + QualType Arg = S.Context.getCanonicalType(ArgIn); // C++0x [temp.deduct.call]p4 bullet 1: // - If the original P is a reference type, the deduced A (i.e., the type @@ -376,10 +376,10 @@ DeduceTemplateArguments(ASTContext &Context, // transformed A. if (TDF & TDF_ParamWithReferenceType) { Qualifiers Quals; - QualType UnqualParam = Context.getUnqualifiedArrayType(Param, Quals); + QualType UnqualParam = S.Context.getUnqualifiedArrayType(Param, Quals); Quals.setCVRQualifiers(Quals.getCVRQualifiers() & Arg.getCVRQualifiersThroughArrayTypes()); - Param = Context.getQualifiedType(UnqualParam, Quals); + Param = S.Context.getQualifiedType(UnqualParam, Quals); } // If the parameter type is not dependent, there is nothing to deduce. @@ -409,9 +409,9 @@ DeduceTemplateArguments(ASTContext &Context, // FIXME: address spaces, ObjC GC qualifiers if (isa<ArrayType>(Arg)) { Qualifiers Quals; - Arg = Context.getUnqualifiedArrayType(Arg, Quals); + Arg = S.Context.getUnqualifiedArrayType(Arg, Quals); if (Quals) { - Arg = Context.getQualifiedType(Arg, Quals); + Arg = S.Context.getQualifiedType(Arg, Quals); RecanonicalizeArg = true; } } @@ -426,11 +426,11 @@ DeduceTemplateArguments(ASTContext &Context, } assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); - assert(Arg != Context.OverloadTy && "Unresolved overloaded function"); + assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function"); QualType DeducedType = Arg; DeducedType.removeCVRQualifiers(Param.getCVRQualifiers()); if (RecanonicalizeArg) - DeducedType = Context.getCanonicalType(DeducedType); + DeducedType = S.Context.getCanonicalType(DeducedType); if (Deduced[Index].isNull()) Deduced[Index] = TemplateArgument(DeducedType); @@ -479,7 +479,7 @@ DeduceTemplateArguments(ASTContext &Context, return Sema::TDK_NonDeducedMismatch; unsigned SubTDF = TDF & (TDF_IgnoreQualifiers | TDF_DerivedClass); - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, cast<PointerType>(Param)->getPointeeType(), PointerArg->getPointeeType(), Info, Deduced, SubTDF); @@ -491,7 +491,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, cast<LValueReferenceType>(Param)->getPointeeType(), ReferenceArg->getPointeeType(), Info, Deduced, 0); @@ -503,7 +503,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!ReferenceArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, cast<RValueReferenceType>(Param)->getPointeeType(), ReferenceArg->getPointeeType(), Info, Deduced, 0); @@ -512,12 +512,12 @@ DeduceTemplateArguments(ASTContext &Context, // T [] (implied, but not stated explicitly) case Type::IncompleteArray: { const IncompleteArrayType *IncompleteArrayArg = - Context.getAsIncompleteArrayType(Arg); + S.Context.getAsIncompleteArrayType(Arg); if (!IncompleteArrayArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, - Context.getAsIncompleteArrayType(Param)->getElementType(), + return DeduceTemplateArguments(S, TemplateParams, + S.Context.getAsIncompleteArrayType(Param)->getElementType(), IncompleteArrayArg->getElementType(), Info, Deduced, 0); } @@ -525,16 +525,16 @@ DeduceTemplateArguments(ASTContext &Context, // T [integer-constant] case Type::ConstantArray: { const ConstantArrayType *ConstantArrayArg = - Context.getAsConstantArrayType(Arg); + S.Context.getAsConstantArrayType(Arg); if (!ConstantArrayArg) return Sema::TDK_NonDeducedMismatch; const ConstantArrayType *ConstantArrayParm = - Context.getAsConstantArrayType(Param); + S.Context.getAsConstantArrayType(Param); if (ConstantArrayArg->getSize() != ConstantArrayParm->getSize()) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, ConstantArrayParm->getElementType(), ConstantArrayArg->getElementType(), Info, Deduced, 0); @@ -542,15 +542,15 @@ DeduceTemplateArguments(ASTContext &Context, // type [i] case Type::DependentSizedArray: { - const ArrayType *ArrayArg = Context.getAsArrayType(Arg); + const ArrayType *ArrayArg = S.Context.getAsArrayType(Arg); if (!ArrayArg) return Sema::TDK_NonDeducedMismatch; // Check the element type of the arrays const DependentSizedArrayType *DependentArrayParm - = Context.getAsDependentSizedArrayType(Param); + = S.Context.getAsDependentSizedArrayType(Param); if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, DependentArrayParm->getElementType(), ArrayArg->getElementType(), Info, Deduced, 0)) @@ -569,12 +569,12 @@ DeduceTemplateArguments(ASTContext &Context, if (const ConstantArrayType *ConstantArrayArg = dyn_cast<ConstantArrayType>(ArrayArg)) { llvm::APSInt Size(ConstantArrayArg->getSize()); - return DeduceNonTypeTemplateArgument(Context, NTTP, Size, + return DeduceNonTypeTemplateArgument(S, NTTP, Size, Info, Deduced); } if (const DependentSizedArrayType *DependentArrayArg = dyn_cast<DependentSizedArrayType>(ArrayArg)) - return DeduceNonTypeTemplateArgument(Context, NTTP, + return DeduceNonTypeTemplateArgument(S, NTTP, DependentArrayArg->getSizeExpr(), Info, Deduced); @@ -606,7 +606,7 @@ DeduceTemplateArguments(ASTContext &Context, // Check return types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, FunctionProtoParam->getResultType(), FunctionProtoArg->getResultType(), Info, Deduced, 0)) @@ -615,7 +615,7 @@ DeduceTemplateArguments(ASTContext &Context, for (unsigned I = 0, N = FunctionProtoParam->getNumArgs(); I != N; ++I) { // Check argument types. if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, FunctionProtoParam->getArgType(I), FunctionProtoArg->getArgType(I), Info, Deduced, 0)) @@ -636,7 +636,7 @@ DeduceTemplateArguments(ASTContext &Context, // Try to deduce template arguments from the template-id. Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, SpecParam, Arg, + = DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg, Info, Deduced); if (Result && (TDF & TDF_DerivedClass)) { @@ -649,7 +649,13 @@ DeduceTemplateArguments(ASTContext &Context, // More importantly: // These alternatives are considered only if type deduction would // otherwise fail. - if (const RecordType *RecordT = dyn_cast<RecordType>(Arg)) { + if (const RecordType *RecordT = Arg->getAs<RecordType>()) { + // We cannot inspect base classes as part of deduction when the type + // is incomplete, so either instantiate any templates necessary to + // complete the type, or skip over it if it cannot be completed. + if (S.RequireCompleteType(Info.getLocation(), Arg, 0)) + return Result; + // Use data recursion to crawl through the list of base classes. // Visited contains the set of nodes we have already visited, while // ToVisit is our stack of records that we still need to visit. @@ -670,7 +676,7 @@ DeduceTemplateArguments(ASTContext &Context, // deduction from it. if (NextT != RecordT) { Sema::TemplateDeductionResult BaseResult - = DeduceTemplateArguments(Context, TemplateParams, SpecParam, + = DeduceTemplateArguments(S, TemplateParams, SpecParam, QualType(NextT, 0), Info, Deduced); // If template argument deduction for this base was successful, @@ -715,14 +721,14 @@ DeduceTemplateArguments(ASTContext &Context, return Sema::TDK_NonDeducedMismatch; if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, MemPtrParam->getPointeeType(), MemPtrArg->getPointeeType(), Info, Deduced, TDF & TDF_IgnoreQualifiers)) return Result; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, QualType(MemPtrParam->getClass(), 0), QualType(MemPtrArg->getClass(), 0), Info, Deduced, 0); @@ -740,7 +746,7 @@ DeduceTemplateArguments(ASTContext &Context, if (!BlockPtrArg) return Sema::TDK_NonDeducedMismatch; - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, BlockPtrParam->getPointeeType(), BlockPtrArg->getPointeeType(), Info, Deduced, 0); @@ -761,7 +767,7 @@ DeduceTemplateArguments(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgument &Param, const TemplateArgument &Arg, @@ -774,7 +780,7 @@ DeduceTemplateArguments(ASTContext &Context, case TemplateArgument::Type: if (Arg.getKind() == TemplateArgument::Type) - return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(), + return DeduceTemplateArguments(S, TemplateParams, Param.getAsType(), Arg.getAsType(), Info, Deduced, 0); Info.FirstArg = Param; Info.SecondArg = Arg; @@ -782,7 +788,7 @@ DeduceTemplateArguments(ASTContext &Context, case TemplateArgument::Template: if (Arg.getKind() == TemplateArgument::Template) - return DeduceTemplateArguments(Context, TemplateParams, + return DeduceTemplateArguments(S, TemplateParams, Param.getAsTemplate(), Arg.getAsTemplate(), Info, Deduced); Info.FirstArg = Param; @@ -826,14 +832,14 @@ DeduceTemplateArguments(ASTContext &Context, = getDeducedParameterFromExpr(Param.getAsExpr())) { if (Arg.getKind() == TemplateArgument::Integral) // FIXME: Sign problems here - return DeduceNonTypeTemplateArgument(Context, NTTP, + return DeduceNonTypeTemplateArgument(S, NTTP, *Arg.getAsIntegral(), Info, Deduced); if (Arg.getKind() == TemplateArgument::Expression) - return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsExpr(), + return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsExpr(), Info, Deduced); if (Arg.getKind() == TemplateArgument::Declaration) - return DeduceNonTypeTemplateArgument(Context, NTTP, Arg.getAsDecl(), + return DeduceNonTypeTemplateArgument(S, NTTP, Arg.getAsDecl(), Info, Deduced); assert(false && "Type/value mismatch"); @@ -854,7 +860,7 @@ DeduceTemplateArguments(ASTContext &Context, } static Sema::TemplateDeductionResult -DeduceTemplateArguments(ASTContext &Context, +DeduceTemplateArguments(Sema &S, TemplateParameterList *TemplateParams, const TemplateArgumentList &ParamList, const TemplateArgumentList &ArgList, @@ -863,7 +869,7 @@ DeduceTemplateArguments(ASTContext &Context, assert(ParamList.size() == ArgList.size()); for (unsigned I = 0, N = ParamList.size(); I != N; ++I) { if (Sema::TemplateDeductionResult Result - = DeduceTemplateArguments(Context, TemplateParams, + = DeduceTemplateArguments(S, TemplateParams, ParamList[I], ArgList[I], Info, Deduced)) return Result; @@ -951,7 +957,7 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial, llvm::SmallVector<TemplateArgument, 4> Deduced; Deduced.resize(Partial->getTemplateParameters()->size()); if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, + = ::DeduceTemplateArguments(*this, Partial->getTemplateParameters(), Partial->getTemplateArgs(), TemplateArgs, Info, Deduced)) @@ -1306,6 +1312,91 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, return TDK_Success; } +static QualType GetTypeOfFunction(ASTContext &Context, + bool isAddressOfOperand, + FunctionDecl *Fn) { + if (!isAddressOfOperand) return Fn->getType(); + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) + if (Method->isInstance()) + return Context.getMemberPointerType(Fn->getType(), + Context.getTypeDeclType(Method->getParent()).getTypePtr()); + return Context.getPointerType(Fn->getType()); +} + +/// Apply the deduction rules for overload sets. +/// +/// \return the null type if this argument should be treated as an +/// undeduced context +static QualType +ResolveOverloadForDeduction(Sema &S, TemplateParameterList *TemplateParams, + Expr *Arg, QualType ParamType) { + llvm::PointerIntPair<OverloadExpr*,1> R = OverloadExpr::find(Arg); + + bool isAddressOfOperand = bool(R.getInt()); + OverloadExpr *Ovl = R.getPointer(); + + // If there were explicit template arguments, we can only find + // something via C++ [temp.arg.explicit]p3, i.e. if the arguments + // unambiguously name a full specialization. + if (Ovl->hasExplicitTemplateArgs()) { + // But we can still look for an explicit specialization. + if (FunctionDecl *ExplicitSpec + = S.ResolveSingleFunctionTemplateSpecialization(Ovl)) + return GetTypeOfFunction(S.Context, isAddressOfOperand, ExplicitSpec); + return QualType(); + } + + // C++0x [temp.deduct.call]p6: + // When P is a function type, pointer to function type, or pointer + // to member function type: + + if (!ParamType->isFunctionType() && + !ParamType->isFunctionPointerType() && + !ParamType->isMemberFunctionPointerType()) + return QualType(); + + QualType Match; + for (UnresolvedSetIterator I = Ovl->decls_begin(), + E = Ovl->decls_end(); I != E; ++I) { + NamedDecl *D = (*I)->getUnderlyingDecl(); + + // - If the argument is an overload set containing one or more + // function templates, the parameter is treated as a + // non-deduced context. + if (isa<FunctionTemplateDecl>(D)) + return QualType(); + + FunctionDecl *Fn = cast<FunctionDecl>(D); + QualType ArgType = GetTypeOfFunction(S.Context, isAddressOfOperand, Fn); + + // - If the argument is an overload set (not containing function + // templates), trial argument deduction is attempted using each + // of the members of the set. If deduction succeeds for only one + // of the overload set members, that member is used as the + // argument value for the deduction. If deduction succeeds for + // more than one member of the overload set the parameter is + // treated as a non-deduced context. + + // We do all of this in a fresh context per C++0x [temp.deduct.type]p2: + // Type deduction is done independently for each P/A pair, and + // the deduced template argument values are then combined. + // So we do not reject deductions which were made elsewhere. + llvm::SmallVector<TemplateArgument, 8> Deduced(TemplateParams->size()); + Sema::TemplateDeductionInfo Info(S.Context, Ovl->getNameLoc()); + unsigned TDF = 0; + + Sema::TemplateDeductionResult Result + = DeduceTemplateArguments(S, TemplateParams, + ParamType, ArgType, + Info, Deduced, TDF); + if (Result) continue; + if (!Match.isNull()) return QualType(); + Match = ArgType; + } + + return Match; +} + /// \brief Perform template argument deduction from a function call /// (C++ [temp.deduct.call]). /// @@ -1384,6 +1475,15 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, QualType ParamType = ParamTypes[I]; QualType ArgType = Args[I]->getType(); + // Overload sets usually make this parameter an undeduced + // context, but there are sometimes special circumstances. + if (ArgType == Context.OverloadTy) { + ArgType = ResolveOverloadForDeduction(*this, TemplateParams, + Args[I], ParamType); + if (ArgType.isNull()) + continue; + } + // C++ [temp.deduct.call]p2: // If P is not a reference type: QualType CanonParamType = Context.getCanonicalType(ParamType); @@ -1454,38 +1554,8 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, ParamType->getAs<PointerType>()->getPointeeType()))) TDF |= TDF_DerivedClass; - // FIXME: C++0x [temp.deduct.call] paragraphs 6-9 deal with function - // pointer parameters. - - if (Context.hasSameUnqualifiedType(ArgType, Context.OverloadTy)) { - // We know that template argument deduction will fail if the argument is - // still an overloaded function. Check whether we can resolve this - // argument as a single function template specialization per - // C++ [temp.arg.explicit]p3. - FunctionDecl *ExplicitSpec - = ResolveSingleFunctionTemplateSpecialization(Args[I]); - Expr *ResolvedArg = 0; - if (ExplicitSpec) - ResolvedArg = FixOverloadedFunctionReference(Args[I], ExplicitSpec); - if (!ExplicitSpec || !ResolvedArg) { - // Template argument deduction fails if we can't resolve the overloaded - // function. - return TDK_FailedOverloadResolution; - } - - // Get the type of the resolved argument, and adjust it per - // C++0x [temp.deduct.call]p3. - ArgType = ResolvedArg->getType(); - if (!ParamWasReference && ArgType->isFunctionType()) - ArgType = Context.getPointerType(ArgType); - if (ArgType->isPointerType() || ArgType->isMemberPointerType()) - TDF |= TDF_IgnoreQualifiers; - - ResolvedArg->Destroy(Context); - } - if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, + = ::DeduceTemplateArguments(*this, TemplateParams, ParamType, ArgType, Info, Deduced, TDF)) return Result; @@ -1548,11 +1618,12 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // Trap any errors that might occur. SFINAETrap Trap(*this); + Deduced.resize(TemplateParams->size()); + if (!ArgFunctionType.isNull()) { // Deduce template arguments from the function type. - Deduced.resize(TemplateParams->size()); if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, + = ::DeduceTemplateArguments(*this, TemplateParams, FunctionType, ArgFunctionType, Info, Deduced, 0)) return Result; @@ -1651,7 +1722,7 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, (P->isMemberPointerType() && P->isMemberPointerType())) TDF |= TDF_IgnoreQualifiers; if (TemplateDeductionResult Result - = ::DeduceTemplateArguments(Context, TemplateParams, + = ::DeduceTemplateArguments(*this, TemplateParams, P, A, Info, Deduced, TDF)) return Result; @@ -1702,7 +1773,7 @@ enum DeductionQualifierComparison { /// \brief Deduce the template arguments during partial ordering by comparing /// the parameter type and the argument type (C++0x [temp.deduct.partial]). /// -/// \param Context the AST context in which this deduction occurs. +/// \param S the semantic analysis object within which we are deducing /// /// \param TemplateParams the template parameters that we are deducing /// @@ -1718,14 +1789,14 @@ enum DeductionQualifierComparison { /// "success" result means that template argument deduction has not yet failed, /// but it may still fail, later, for other reasons. static Sema::TemplateDeductionResult -DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, +DeduceTemplateArgumentsDuringPartialOrdering(Sema &S, TemplateParameterList *TemplateParams, QualType ParamIn, QualType ArgIn, Sema::TemplateDeductionInfo &Info, llvm::SmallVectorImpl<TemplateArgument> &Deduced, llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) { - CanQualType Param = Context.getCanonicalType(ParamIn); - CanQualType Arg = Context.getCanonicalType(ArgIn); + CanQualType Param = S.Context.getCanonicalType(ParamIn); + CanQualType Arg = S.Context.getCanonicalType(ArgIn); // C++0x [temp.deduct.partial]p5: // Before the partial ordering is done, certain transformations are @@ -1772,7 +1843,7 @@ DeduceTemplateArgumentsDuringPartialOrdering(ASTContext &Context, // described in 14.9.2.5. If deduction succeeds for a given type, the type // from the argument template is considered to be at least as specialized // as the type from the parameter template. - return DeduceTemplateArguments(Context, TemplateParams, Param, Arg, Info, + return DeduceTemplateArguments(S, TemplateParams, Param, Arg, Info, Deduced, TDF_None); } @@ -1785,6 +1856,7 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, /// \brief Determine whether the function template \p FT1 is at least as /// specialized as \p FT2. static bool isAtLeastAsSpecializedAs(Sema &S, + SourceLocation Loc, FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, TemplatePartialOrderingContext TPOC, @@ -1802,14 +1874,14 @@ static bool isAtLeastAsSpecializedAs(Sema &S, // C++0x [temp.deduct.partial]p3: // The types used to determine the ordering depend on the context in which // the partial ordering is done: - Sema::TemplateDeductionInfo Info(S.Context); + Sema::TemplateDeductionInfo Info(S.Context, Loc); switch (TPOC) { case TPOC_Call: { // - In the context of a function call, the function parameter types are // used. unsigned NumParams = std::min(Proto1->getNumArgs(), Proto2->getNumArgs()); for (unsigned I = 0; I != NumParams; ++I) - if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context, + if (DeduceTemplateArgumentsDuringPartialOrdering(S, TemplateParams, Proto2->getArgType(I), Proto1->getArgType(I), @@ -1824,7 +1896,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, case TPOC_Conversion: // - In the context of a call to a conversion operator, the return types // of the conversion function templates are used. - if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context, + if (DeduceTemplateArgumentsDuringPartialOrdering(S, TemplateParams, Proto2->getResultType(), Proto1->getResultType(), @@ -1837,7 +1909,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, case TPOC_Other: // - In other contexts (14.6.6.2) the function template’s function type // is used. - if (DeduceTemplateArgumentsDuringPartialOrdering(S.Context, + if (DeduceTemplateArgumentsDuringPartialOrdering(S, TemplateParams, FD2->getType(), FD1->getType(), @@ -1916,10 +1988,11 @@ static bool isAtLeastAsSpecializedAs(Sema &S, FunctionTemplateDecl * Sema::getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, + SourceLocation Loc, TemplatePartialOrderingContext TPOC) { llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons; - bool Better1 = isAtLeastAsSpecializedAs(*this, FT1, FT2, TPOC, 0); - bool Better2 = isAtLeastAsSpecializedAs(*this, FT2, FT1, TPOC, + bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC, 0); + bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC, &QualifierComparisons); if (Better1 != Better2) // We have a clear winner @@ -1987,11 +2060,11 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// \brief Retrieve the most specialized of the given function template /// specializations. /// -/// \param Specializations the set of function template specializations that -/// we will be comparing. +/// \param SpecBegin the start iterator of the function template +/// specializations that we will be comparing. /// -/// \param NumSpecializations the number of function template specializations in -/// \p Specializations +/// \param SpecEnd the end iterator of the function template +/// specializations, paired with \p SpecBegin. /// /// \param TPOC the partial ordering context to use to compare the function /// template specializations. @@ -2015,42 +2088,38 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// specialization. /// /// \returns the most specialized function template specialization, if -/// found. Otherwise, returns NULL. +/// found. Otherwise, returns SpecEnd. /// /// \todo FIXME: Consider passing in the "also-ran" candidates that failed /// template argument deduction. -FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, - unsigned NumSpecializations, - TemplatePartialOrderingContext TPOC, - SourceLocation Loc, - const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, - const PartialDiagnostic &CandidateDiag, - unsigned *Index) { - if (NumSpecializations == 0) { +UnresolvedSetIterator +Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, + UnresolvedSetIterator SpecEnd, + TemplatePartialOrderingContext TPOC, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag) { + if (SpecBegin == SpecEnd) { Diag(Loc, NoneDiag); - return 0; + return SpecEnd; } - if (NumSpecializations == 1) { - if (Index) - *Index = 0; - - return Specializations[0]; - } - + if (SpecBegin + 1 == SpecEnd) + return SpecBegin; // Find the function template that is better than all of the templates it // has been compared to. - unsigned Best = 0; + UnresolvedSetIterator Best = SpecBegin; FunctionTemplateDecl *BestTemplate - = Specializations[Best]->getPrimaryTemplate(); + = cast<FunctionDecl>(*Best)->getPrimaryTemplate(); assert(BestTemplate && "Not a function template specialization?"); - for (unsigned I = 1; I != NumSpecializations; ++I) { - FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate(); + for (UnresolvedSetIterator I = SpecBegin + 1; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); assert(Challenger && "Not a function template specialization?"); - if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, - TPOC), + if (isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, + Loc, TPOC), Challenger)) { Best = I; BestTemplate = Challenger; @@ -2060,11 +2129,12 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, // Make sure that the "best" function template is more specialized than all // of the others. bool Ambiguous = false; - for (unsigned I = 0; I != NumSpecializations; ++I) { - FunctionTemplateDecl *Challenger = Specializations[I]->getPrimaryTemplate(); + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) { + FunctionTemplateDecl *Challenger + = cast<FunctionDecl>(*I)->getPrimaryTemplate(); if (I != Best && !isSameTemplate(getMoreSpecializedTemplate(BestTemplate, Challenger, - TPOC), + Loc, TPOC), BestTemplate)) { Ambiguous = true; break; @@ -2073,22 +2143,20 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, if (!Ambiguous) { // We found an answer. Return it. - if (Index) - *Index = Best; - return Specializations[Best]; + return Best; } // Diagnose the ambiguity. Diag(Loc, AmbigDiag); // FIXME: Can we order the candidates in some sane way? - for (unsigned I = 0; I != NumSpecializations; ++I) - Diag(Specializations[I]->getLocation(), CandidateDiag) + for (UnresolvedSetIterator I = SpecBegin; I != SpecEnd; ++I) + Diag((*I)->getLocation(), CandidateDiag) << getTemplateArgumentBindingsText( - Specializations[I]->getPrimaryTemplate()->getTemplateParameters(), - *Specializations[I]->getTemplateSpecializationArgs()); + cast<FunctionDecl>(*I)->getPrimaryTemplate()->getTemplateParameters(), + *cast<FunctionDecl>(*I)->getTemplateSpecializationArgs()); - return 0; + return SpecEnd; } /// \brief Returns the more specialized class template partial specialization @@ -2104,7 +2172,8 @@ FunctionDecl *Sema::getMostSpecialized(FunctionDecl **Specializations, ClassTemplatePartialSpecializationDecl * Sema::getMoreSpecializedPartialSpecialization( ClassTemplatePartialSpecializationDecl *PS1, - ClassTemplatePartialSpecializationDecl *PS2) { + ClassTemplatePartialSpecializationDecl *PS2, + SourceLocation Loc) { // C++ [temp.class.order]p1: // For two class template partial specializations, the first is at least as // specialized as the second if, given the following rewrite to two @@ -2127,11 +2196,11 @@ Sema::getMoreSpecializedPartialSpecialization( // template partial ordering, because class template partial specializations // are more constrained. We know that every template parameter is deduc llvm::SmallVector<TemplateArgument, 4> Deduced; - Sema::TemplateDeductionInfo Info(Context); + Sema::TemplateDeductionInfo Info(Context, Loc); // Determine whether PS1 is at least as specialized as PS2 Deduced.resize(PS2->getTemplateParameters()->size()); - bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(Context, + bool Better1 = !DeduceTemplateArgumentsDuringPartialOrdering(*this, PS2->getTemplateParameters(), Context.getTypeDeclType(PS2), Context.getTypeDeclType(PS1), @@ -2142,7 +2211,7 @@ Sema::getMoreSpecializedPartialSpecialization( // Determine whether PS2 is at least as specialized as PS1 Deduced.clear(); Deduced.resize(PS1->getTemplateParameters()->size()); - bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(Context, + bool Better2 = !DeduceTemplateArgumentsDuringPartialOrdering(*this, PS1->getTemplateParameters(), Context.getTypeDeclType(PS1), Context.getTypeDeclType(PS2), diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2db0deb..51e17fe 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -33,9 +33,15 @@ using namespace clang; /// arguments. /// /// \param Innermost if non-NULL, the innermost template argument list. +/// +/// \param RelativeToPrimary true if we should get the template +/// arguments relative to the primary template, even when we're +/// dealing with a specialization. This is only relevant for function +/// template specializations. MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(NamedDecl *D, - const TemplateArgumentList *Innermost) { + const TemplateArgumentList *Innermost, + bool RelativeToPrimary) { // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; @@ -64,8 +70,9 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, } // Add template arguments from a function template specialization. else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) { - if (Function->getTemplateSpecializationKind() - == TSK_ExplicitSpecialization) + if (!RelativeToPrimary && + Function->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) break; if (const TemplateArgumentList *TemplateArgs @@ -86,11 +93,13 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, if (Function->getFriendObjectKind() && Function->getDeclContext()->isFileContext()) { Ctx = Function->getLexicalDeclContext(); + RelativeToPrimary = false; continue; } } Ctx = Ctx->getParent(); + RelativeToPrimary = false; } return Result; @@ -555,6 +564,8 @@ namespace { Sema::OwningExprResult TransformPredefinedExpr(PredefinedExpr *E); Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E); Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E); + Sema::OwningExprResult TransformTemplateParmRefExpr(DeclRefExpr *E, + NonTypeTemplateParmDecl *D); /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. @@ -569,6 +580,14 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { if (TTP->getDepth() < TemplateArgs.getNumLevels()) { + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(), + TTP->getPosition())) + return D; + TemplateName Template = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate(); assert(!Template.isNull() && Template.getAsTemplateDecl() && @@ -576,14 +595,6 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { return Template.getAsTemplateDecl(); } - // If the corresponding template argument is NULL or non-existent, it's - // because we are performing instantiation from explicitly-specified - // template arguments in a function template, but there were some - // arguments left unspecified. - if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(), - TTP->getPosition())) - return D; - // Fall through to find the instantiated declaration for this template // template parameter. } @@ -676,8 +687,7 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { PredefinedExpr::IdentType IT = E->getIdentType(); - unsigned Length = - PredefinedExpr::ComputeName(getSema().Context, IT, currentDecl).length(); + unsigned Length = PredefinedExpr::ComputeName(IT, currentDecl).length(); llvm::APInt LengthI(32, Length + 1); QualType ResTy = getSema().Context.CharTy.withConst(); @@ -689,88 +699,145 @@ TemplateInstantiator::TransformPredefinedExpr(PredefinedExpr *E) { } Sema::OwningExprResult -TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { - // FIXME: Clean this up a bit - NamedDecl *D = E->getDecl(); - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { - if (NTTP->getDepth() < TemplateArgs.getNumLevels()) { - // If the corresponding template argument is NULL or non-existent, it's - // because we are performing instantiation from explicitly-specified - // template arguments in a function template, but there were some - // arguments left unspecified. - if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), - NTTP->getPosition())) - return SemaRef.Owned(E->Retain()); +TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, + NonTypeTemplateParmDecl *NTTP) { + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), + NTTP->getPosition())) + return SemaRef.Owned(E->Retain()); - const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), - NTTP->getPosition()); + const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(), + NTTP->getPosition()); - // The template argument itself might be an expression, in which - // case we just return that expression. - if (Arg.getKind() == TemplateArgument::Expression) - return SemaRef.Owned(Arg.getAsExpr()->Retain()); + // The template argument itself might be an expression, in which + // case we just return that expression. + if (Arg.getKind() == TemplateArgument::Expression) + return SemaRef.Owned(Arg.getAsExpr()->Retain()); - if (Arg.getKind() == TemplateArgument::Declaration) { - ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + if (Arg.getKind() == TemplateArgument::Declaration) { + ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); - VD = cast_or_null<ValueDecl>( + // Find the instantiation of the template argument. This is + // required for nested templates. + VD = cast_or_null<ValueDecl>( getSema().FindInstantiatedDecl(VD, TemplateArgs)); - if (!VD) + if (!VD) + return SemaRef.ExprError(); + + // Derive the type we want the substituted decl to have. This had + // better be non-dependent, or these checks will have serious problems. + QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, + E->getLocation(), + DeclarationName()); + assert(!TargetType.isNull() && "type substitution failed for param type"); + assert(!TargetType->isDependentType() && "param type still dependent"); + + if (VD->getDeclContext()->isRecord() && + (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD))) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (TargetType->isMemberPointerType()) { + QualType ClassType + = SemaRef.Context.getTypeDeclType( + cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr + = SemaRef.BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + E->getLocation(), + &SS); + if (RefExpr.isInvalid()) return SemaRef.ExprError(); - if (VD->getDeclContext()->isRecord()) { - // If the value is a class member, we might have a pointer-to-member. - // Determine whether the non-type template template parameter is of - // pointer-to-member type. If so, we need to build an appropriate - // expression for a pointer-to-member, since a "normal" DeclRefExpr - // would refer to the member itself. - if (NTTP->getType()->isMemberPointerType()) { - QualType ClassType - = SemaRef.Context.getTypeDeclType( - cast<RecordDecl>(VD->getDeclContext())); - NestedNameSpecifier *Qualifier - = NestedNameSpecifier::Create(SemaRef.Context, 0, false, - ClassType.getTypePtr()); - CXXScopeSpec SS; - SS.setScopeRep(Qualifier); - OwningExprResult RefExpr - = SemaRef.BuildDeclRefExpr(VD, - VD->getType().getNonReferenceType(), - E->getLocation(), - &SS); - if (RefExpr.isInvalid()) - return SemaRef.ExprError(); - - return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), - UnaryOperator::AddrOf, - move(RefExpr)); - } - } + RefExpr = SemaRef.CreateBuiltinUnaryOp(E->getLocation(), + UnaryOperator::AddrOf, + move(RefExpr)); + assert(!RefExpr.isInvalid() && + SemaRef.Context.hasSameType(((Expr*) RefExpr.get())->getType(), + TargetType)); + return move(RefExpr); + } + } - return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), - E->getLocation()); + QualType T = VD->getType().getNonReferenceType(); + + if (TargetType->isPointerType()) { + // C++03 [temp.arg.nontype]p5: + // - For a non-type template-parameter of type pointer to + // object, qualification conversions and the array-to-pointer + // conversion are applied. + // - For a non-type template-parameter of type pointer to + // function, only the function-to-pointer conversion is + // applied. + + OwningExprResult RefExpr + = SemaRef.BuildDeclRefExpr(VD, T, E->getLocation()); + if (RefExpr.isInvalid()) + return SemaRef.ExprError(); + + // Decay functions and arrays. + Expr *RefE = (Expr *)RefExpr.get(); + SemaRef.DefaultFunctionArrayConversion(RefE); + if (RefE != RefExpr.get()) { + RefExpr.release(); + RefExpr = SemaRef.Owned(RefE); } - assert(Arg.getKind() == TemplateArgument::Integral); - QualType T = Arg.getIntegralType(); - if (T->isCharType() || T->isWideCharType()) - return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( + // Qualification conversions. + RefExpr.release(); + SemaRef.ImpCastExprToType(RefE, TargetType.getUnqualifiedType(), + CastExpr::CK_NoOp); + return SemaRef.Owned(RefE); + } + + // If the non-type template parameter has reference type, qualify the + // resulting declaration reference with the extra qualifiers on the + // type that the reference refers to. + if (const ReferenceType *TargetRef = TargetType->getAs<ReferenceType>()) + T = SemaRef.Context.getQualifiedType(T, + TargetRef->getPointeeType().getQualifiers()); + + return SemaRef.BuildDeclRefExpr(VD, T, E->getLocation()); + } + + assert(Arg.getKind() == TemplateArgument::Integral); + QualType T = Arg.getIntegralType(); + if (T->isCharType() || T->isWideCharType()) + return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral( Arg.getAsIntegral()->getZExtValue(), T->isWideCharType(), T, E->getSourceRange().getBegin())); - if (T->isBooleanType()) - return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr( + if (T->isBooleanType()) + return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr( Arg.getAsIntegral()->getBoolValue(), T, E->getSourceRange().getBegin())); - assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T)); - return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( + assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T)); + return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral( *Arg.getAsIntegral(), T, E->getSourceRange().getBegin())); - } +} + + +Sema::OwningExprResult +TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) { + NamedDecl *D = E->getDecl(); + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { + if (NTTP->getDepth() < TemplateArgs.getNumLevels()) + return TransformTemplateParmRefExpr(E, NTTP); // We have a non-type template parameter that isn't fully substituted; // FindInstantiatedDecl will find it in the local instantiation scope. @@ -986,7 +1053,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, bool Invalid = false; CXXRecordDecl *PatternDef - = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); + = cast_or_null<CXXRecordDecl>(Pattern->getDefinition()); if (!PatternDef) { if (!Complain) { // Say nothing @@ -1063,9 +1130,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // If this is a polymorphic C++ class without a key function, we'll // have to mark all of the virtual members to allow emission of a vtable // in this translation unit. - if (Instantiation->isDynamicClass() && !Context.getKeyFunction(Instantiation)) + if (Instantiation->isDynamicClass() && + !Context.getKeyFunction(Instantiation)) { + // Local classes need to have their methods instantiated immediately in + // order to have the correct instantiation scope. + if (Instantiation->isLocalClass()) { + MarkVirtualMembersReferenced(PointOfInstantiation, + Instantiation); + } else { ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Instantiation, PointOfInstantiation)); + } + } if (!Invalid) Consumer.HandleTagDeclDefinition(Instantiation); @@ -1124,7 +1200,7 @@ Sema::InstantiateClassTemplateSpecialization( PartialEnd = Template->getPartialSpecializations().end(); Partial != PartialEnd; ++Partial) { - TemplateDeductionInfo Info(Context); + TemplateDeductionInfo Info(Context, PointOfInstantiation); if (TemplateDeductionResult Result = DeduceTemplateArguments(&*Partial, ClassTemplateSpec->getTemplateArgs(), @@ -1154,7 +1230,8 @@ Sema::InstantiateClassTemplateSpecialization( for (llvm::SmallVector<MatchResult, 4>::iterator P = Best + 1, PEnd = Matched.end(); P != PEnd; ++P) { - if (getMoreSpecializedPartialSpecialization(P->first, Best->first) + if (getMoreSpecializedPartialSpecialization(P->first, Best->first, + PointOfInstantiation) == P->first) Best = P; } @@ -1166,7 +1243,8 @@ Sema::InstantiateClassTemplateSpecialization( PEnd = Matched.end(); P != PEnd; ++P) { if (P != Best && - getMoreSpecializedPartialSpecialization(P->first, Best->first) + getMoreSpecializedPartialSpecialization(P->first, Best->first, + PointOfInstantiation) != Best->first) { Ambiguous = true; break; @@ -1327,8 +1405,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass(); assert(Pattern && "Missing instantiated-from-template information"); - if (!Record->getDefinition(Context)) { - if (!Pattern->getDefinition(Context)) { + if (!Record->getDefinition()) { + if (!Pattern->getDefinition()) { // C++0x [temp.explicit]p8: // An explicit instantiation definition that names a class template // specialization explicitly instantiates the class template @@ -1348,7 +1426,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, TSK); } - Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); + Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition()); if (Pattern) InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs, TSK); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 23a9430..0b0efcb 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -43,6 +43,7 @@ namespace { // clang/AST/DeclNodes.def. Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitFieldDecl(FieldDecl *D); @@ -126,6 +127,21 @@ TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { return D; } +Decl * +TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + NamespaceAliasDecl *Inst + = NamespaceAliasDecl::Create(SemaRef.Context, Owner, + D->getNamespaceLoc(), + D->getAliasLoc(), + D->getNamespace()->getIdentifier(), + D->getQualifierRange(), + D->getQualifier(), + D->getTargetNameLoc(), + D->getNamespace()); + Owner->addDecl(Inst); + return Inst; +} + Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); @@ -217,6 +233,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // FIXME: having to fake up a LookupResult is dumb. LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(), Sema::LookupOrdinaryName); + if (D->isStaticDataMember()) + SemaRef.LookupQualifiedName(Previous, Owner, false); SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration); if (D->isOutOfLine()) { @@ -232,7 +250,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { SemaRef.Context.setInstantiatedFromStaticDataMember(Var, D, TSK_ImplicitInstantiation); - if (D->getInit()) { + if (Var->getAnyInitializer()) { + // We already have an initializer in the class. + } else if (D->getInit()) { if (Var->isStaticDataMember() && !D->isOutOfLine()) SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated); else @@ -241,6 +261,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Extract the initializer, skipping through any temporary-binding // expressions and look at the subexpression as it was written. Expr *DInit = D->getInit(); + if (CXXExprWithTemporaries *ExprTemp + = dyn_cast<CXXExprWithTemporaries>(DInit)) + DInit = ExprTemp->getSubExpr(); while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(DInit)) DInit = Binder->getSubExpr(); if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(DInit)) @@ -408,9 +431,17 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { Decl *NewND; // Hack to make this work almost well pending a rewrite. - if (ND->getDeclContext()->isRecord()) - NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs); - else if (D->wasSpecialization()) { + if (ND->getDeclContext()->isRecord()) { + if (!ND->getDeclContext()->isDependentContext()) { + NewND = SemaRef.FindInstantiatedDecl(ND, TemplateArgs); + } else { + // FIXME: Hack to avoid crashing when incorrectly trying to instantiate + // templated friend declarations. This doesn't produce a correct AST; + // however this is sufficient for some AST analysis. The real solution + // must be put in place during the pending rewrite. See PR5848. + return 0; + } + } else if (D->wasSpecialization()) { // Totally egregious hack to work around PR5866 return 0; } else @@ -493,6 +524,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } if (EnumConst) { + EnumConst->setAccess(Enum->getAccess()); Enum->addDecl(EnumConst); Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst)); LastEnumConst = EnumConst; @@ -734,9 +766,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, if (T.isNull()) return 0; - // Build the instantiated method declaration. - DeclContext *DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), - TemplateArgs); + // If we're instantiating a local function declaration, put the result + // in the owner; otherwise we need to find the instantiated context. + DeclContext *DC; + if (D->getDeclContext()->isFunctionOrMethod()) + DC = Owner; + else + DC = SemaRef.FindInstantiatedContext(D->getDeclContext(), TemplateArgs); + FunctionDecl *Function = FunctionDecl::Create(SemaRef.Context, DC, D->getLocation(), D->getDeclName(), T, D->getTypeSourceInfo(), @@ -747,7 +784,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) Params[P]->setOwningFunction(Function); - Function->setParams(SemaRef.Context, Params.data(), Params.size()); + Function->setParams(Params.data(), Params.size()); if (TemplateParams) { // Our resulting instantiation is actually a function template, since we @@ -772,8 +809,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext()); } else if (FunctionTemplate) { // Record this function template specialization. - Function->setFunctionTemplateSpecialization(SemaRef.Context, - FunctionTemplate, + Function->setFunctionTemplateSpecialization(FunctionTemplate, &TemplateArgs.getInnermost(), InsertPos); } @@ -926,8 +962,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, Method->setDescribedFunctionTemplate(FunctionTemplate); } else if (FunctionTemplate) { // Record this function template specialization. - Method->setFunctionTemplateSpecialization(SemaRef.Context, - FunctionTemplate, + Method->setFunctionTemplateSpecialization(FunctionTemplate, &TemplateArgs.getInnermost(), InsertPos); } else { @@ -944,7 +979,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) Params[P]->setOwningFunction(Method); - Method->setParams(SemaRef.Context, Params.data(), Params.size()); + Method->setParams(Params.data(), Params.size()); if (InitMethodInstantiation(Method, D)) Method->setInvalidDecl(); @@ -1804,7 +1839,6 @@ void Sema::InstantiateStaticDataMemberDefinition( CurContext = PreviousContext; if (Var) { - Var->setPreviousDeclaration(OldVar); MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); assert(MSInfo && "Missing member specialization information?"); Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), @@ -1829,7 +1863,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const MultiLevelTemplateArgumentList &TemplateArgs) { llvm::SmallVector<MemInitTy*, 4> NewInits; - + bool AnyErrors = false; + // Instantiate all the initializers. for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), InitsEnd = Tmpl->init_end(); @@ -1837,26 +1872,38 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, CXXBaseOrMemberInitializer *Init = *Inits; ASTOwningVector<&ActionBase::DeleteExpr> NewArgs(*this); + llvm::SmallVector<SourceLocation, 4> CommaLocs; // Instantiate all the arguments. - for (ExprIterator Args = Init->arg_begin(), ArgsEnd = Init->arg_end(); - Args != ArgsEnd; ++Args) { - OwningExprResult NewArg = SubstExpr(*Args, TemplateArgs); - - if (NewArg.isInvalid()) - New->setInvalidDecl(); - else - NewArgs.push_back(NewArg.takeAs<Expr>()); + Expr *InitE = Init->getInit(); + if (!InitE) { + // Nothing to instantiate; + } else if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(InitE)) { + if (InstantiateInitializationArguments(*this, ParenList->getExprs(), + ParenList->getNumExprs(), + TemplateArgs, CommaLocs, + NewArgs)) { + AnyErrors = true; + continue; + } + } else { + OwningExprResult InitArg = SubstExpr(InitE, TemplateArgs); + if (InitArg.isInvalid()) { + AnyErrors = true; + continue; + } + + NewArgs.push_back(InitArg.release()); } - + MemInitResult NewInit; - if (Init->isBaseInitializer()) { TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), TemplateArgs, Init->getSourceLocation(), New->getDeclName()); if (!BaseTInfo) { + AnyErrors = true; New->setInvalidDecl(); continue; } @@ -1884,9 +1931,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, Init->getRParenLoc()); } - if (NewInit.isInvalid()) + if (NewInit.isInvalid()) { + AnyErrors = true; New->setInvalidDecl(); - else { + } else { // FIXME: It would be nice if ASTOwningVector had a release function. NewArgs.take(); @@ -1898,7 +1946,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, ActOnMemInitializers(DeclPtrTy::make(New), /*FIXME: ColonLoc */ SourceLocation(), - NewInits.data(), NewInits.size()); + NewInits.data(), NewInits.size(), + AnyErrors); } // TODO: this could be templated if the various decl types used the @@ -2140,7 +2189,7 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs) { DeclContext *ParentDC = D->getDeclContext(); if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || - isa<TemplateTypeParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || + isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || ParentDC->isFunctionOrMethod()) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. @@ -2151,10 +2200,11 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, if (!Record->isDependentContext()) return D; - // If the RecordDecl is actually the injected-class-name or a "templated" - // declaration for a class template or class template partial - // specialization, substitute into the injected-class-name of the - // class template or partial specialization to find the new DeclContext. + // If the RecordDecl is actually the injected-class-name or a + // "templated" declaration for a class template, class template + // partial specialization, or a member class of a class template, + // substitute into the injected-class-name of the class template + // or partial specialization to find the new DeclContext. QualType T; ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); @@ -2164,15 +2214,18 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { T = Context.getTypeDeclType(Record); ClassTemplate = PartialSpec->getSpecializedTemplate(); - } + } if (!T.isNull()) { - // Substitute into the injected-class-name to get the type corresponding - // to the instantiation we want. This substitution should never fail, - // since we know we can instantiate the injected-class-name or we wouldn't - // have gotten to the injected-class-name! - // FIXME: Can we use the CurrentInstantiationScope to avoid this extra - // instantiation in the common case? + // Substitute into the injected-class-name to get the type + // corresponding to the instantiation we want, which may also be + // the current instantiation (if we're in a template + // definition). This substitution should never fail, since we + // know we can instantiate the injected-class-name or we + // wouldn't have gotten to the injected-class-name! + + // FIXME: Can we use the CurrentInstantiationScope to avoid this + // extra instantiation in the common case? T = SubstType(T, TemplateArgs, SourceLocation(), DeclarationName()); assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); @@ -2181,26 +2234,37 @@ NamedDecl *Sema::FindInstantiatedDecl(NamedDecl *D, return T->getAs<RecordType>()->getDecl(); } - // We are performing "partial" template instantiation to create the - // member declarations for the members of a class template - // specialization. Therefore, D is actually referring to something in - // the current instantiation. Look through the current context, - // which contains actual instantiations, to find the instantiation of - // the "current instantiation" that D refers to. + // We are performing "partial" template instantiation to create + // the member declarations for the members of a class template + // specialization. Therefore, D is actually referring to something + // in the current instantiation. Look through the current + // context, which contains actual instantiations, to find the + // instantiation of the "current instantiation" that D refers + // to. + bool SawNonDependentContext = false; for (DeclContext *DC = CurContext; !DC->isFileContext(); DC = DC->getParent()) { if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(DC)) + = dyn_cast<ClassTemplateSpecializationDecl>(DC)) if (isInstantiationOf(ClassTemplate, Spec->getSpecializedTemplate())) return Spec; + + if (!DC->isDependentContext()) + SawNonDependentContext = true; } - assert(false && + // We're performing "instantiation" of a member of the current + // instantiation while we are type-checking the + // definition. Compute the declaration context and return that. + assert(!SawNonDependentContext && + "No dependent context while instantiating record"); + DeclContext *DC = computeDeclContext(T); + assert(DC && "Unable to find declaration for the current instantiation"); - return Record; + return cast<CXXRecordDecl>(DC); } - + // Fall through to deal with other dependent record types (e.g., // anonymous unions in class templates). } @@ -2275,6 +2339,24 @@ void Sema::PerformPendingImplicitInstantiations(bool LocalOnly) { VarDecl *Var = cast<VarDecl>(Inst.first); assert(Var->isStaticDataMember() && "Not a static data member?"); + // Don't try to instantiate declarations if the most recent redeclaration + // is invalid. + if (Var->getMostRecentDeclaration()->isInvalidDecl()) + continue; + + // Check if the most recent declaration has changed the specialization kind + // and removed the need for implicit instantiation. + switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { + case TSK_Undeclared: + assert(false && "Cannot instantitiate an undeclared specialization."); + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + case TSK_ExplicitSpecialization: + continue; // No longer need implicit instantiation. + case TSK_ImplicitInstantiation: + break; + } + PrettyStackTraceActionsDecl CrashInfo(DeclPtrTy::make(Var), Var->getLocation(), *this, Context.getSourceManager(), diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9065761..7911e76 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -68,12 +68,41 @@ static bool isOmittedBlockReturnType(const Declarator &D) { return false; } +typedef std::pair<const AttributeList*,QualType> DelayedAttribute; +typedef llvm::SmallVectorImpl<DelayedAttribute> DelayedAttributeSet; + +static void ProcessTypeAttributeList(Sema &S, QualType &Type, + const AttributeList *Attrs, + DelayedAttributeSet &DelayedFnAttrs); +static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr); + +static void ProcessDelayedFnAttrs(Sema &S, QualType &Type, + DelayedAttributeSet &Attrs) { + for (DelayedAttributeSet::iterator I = Attrs.begin(), + E = Attrs.end(); I != E; ++I) + if (ProcessFnAttr(S, Type, *I->first)) + S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type) + << I->first->getName() << I->second; + Attrs.clear(); +} + +static void DiagnoseDelayedFnAttrs(Sema &S, DelayedAttributeSet &Attrs) { + for (DelayedAttributeSet::iterator I = Attrs.begin(), + E = Attrs.end(); I != E; ++I) { + S.Diag(I->first->getLoc(), diag::warn_function_attribute_wrong_type) + << I->first->getName() << I->second; + } + Attrs.clear(); +} + /// \brief Convert the specified declspec to the appropriate type /// object. /// \param D the declarator containing the declaration specifier. /// \returns The type described by the declaration specifiers. This function /// never returns null. -static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ +static QualType ConvertDeclSpecToType(Sema &TheSema, + Declarator &TheDeclarator, + DelayedAttributeSet &Delayed) { // FIXME: Should move the logic from DeclSpec::Finish to here for validity // checking. const DeclSpec &DS = TheDeclarator.getDeclSpec(); @@ -343,6 +372,11 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ if (TheSema.getLangOptions().Freestanding) TheSema.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex); Result = Context.getComplexType(Result); + } 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()); } assert(DS.getTypeSpecComplex() != DeclSpec::TSC_imaginary && @@ -351,7 +385,7 @@ static QualType ConvertDeclSpecToType(Declarator &TheDeclarator, Sema &TheSema){ // See if there are any attributes on the declspec that apply to the type (as // opposed to the decl). if (const AttributeList *AL = DS.getAttributes()) - TheSema.ProcessTypeAttributeList(Result, AL); + ProcessTypeAttributeList(TheSema, Result, AL, Delayed); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -885,15 +919,23 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // have a type. QualType T; + llvm::SmallVector<DelayedAttribute,4> FnAttrsFromDeclSpec; + switch (D.getName().getKind()) { case UnqualifiedId::IK_Identifier: case UnqualifiedId::IK_OperatorFunctionId: case UnqualifiedId::IK_LiteralOperatorId: case UnqualifiedId::IK_TemplateId: - T = ConvertDeclSpecToType(D, *this); + T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec); - if (!D.isInvalidType() && OwnedDecl && D.getDeclSpec().isTypeSpecOwned()) - *OwnedDecl = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep()); + if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) { + TagDecl* Owned = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep()); + // Owned is embedded if it was defined here, or if it is the + // very first (i.e., canonical) declaration of this tag type. + Owned->setEmbeddedInDeclarator(Owned->isDefinition() || + Owned->isCanonicalDecl()); + if (OwnedDecl) *OwnedDecl = Owned; + } break; case UnqualifiedId::IK_ConstructorName: @@ -962,6 +1004,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getIdentifier()) Name = D.getIdentifier(); + llvm::SmallVector<DelayedAttribute,4> FnAttrsFromPreviousChunk; + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -1181,6 +1225,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, FTI.hasAnyExceptionSpec, Exceptions.size(), Exceptions.data()); } + + // For GCC compatibility, we allow attributes that apply only to + // function types to be placed on a function's return type + // instead (as long as that type doesn't happen to be function + // or function-pointer itself). + ProcessDelayedFnAttrs(*this, T, FnAttrsFromPreviousChunk); + break; } case DeclaratorChunk::MemberPointer: @@ -1239,9 +1290,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, T = Context.IntTy; } + DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk); + // See if there are any attributes on this declarator chunk. if (const AttributeList *AL = DeclType.getAttrs()) - ProcessTypeAttributeList(T, AL); + ProcessTypeAttributeList(*this, T, AL, FnAttrsFromPreviousChunk); } if (getLangOptions().CPlusPlus && T->isFunctionType()) { @@ -1271,10 +1324,18 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, } } - // If there were any type attributes applied to the decl itself (not the - // type, apply the type attribute to the type!) - if (const AttributeList *Attrs = D.getAttributes()) - ProcessTypeAttributeList(T, Attrs); + // Process any function attributes we might have delayed from the + // declaration-specifiers. + ProcessDelayedFnAttrs(*this, T, FnAttrsFromDeclSpec); + + // If there were any type attributes applied to the decl itself, not + // the type, apply them to the result type. But don't do this for + // block-literal expressions, which are parsed wierdly. + if (D.getContext() != Declarator::BlockLiteralContext) + if (const AttributeList *Attrs = D.getAttributes()) + ProcessTypeAttributeList(*this, T, Attrs, FnAttrsFromPreviousChunk); + + DiagnoseDelayedFnAttrs(*this, FnAttrsFromPreviousChunk); if (TInfo) { if (D.isInvalidType()) @@ -1645,20 +1706,79 @@ static void HandleObjCGCTypeAttribute(QualType &Type, Type = S.Context.getObjCGCQualType(Type, GCAttr); } -/// HandleNoReturnTypeAttribute - Process the noreturn attribute on the -/// specified type. The attribute contains 0 arguments. -static void HandleNoReturnTypeAttribute(QualType &Type, - const AttributeList &Attr, Sema &S) { - if (Attr.getNumArgs() != 0) - return; +/// Process an individual function attribute. Returns true if the +/// attribute does not make sense to apply to this type. +bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) { + if (Attr.getKind() == AttributeList::AT_noreturn) { + // Complain immediately if the arg count is wrong. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return false; + } - // We only apply this to a pointer to function or a pointer to block. - if (!Type->isFunctionPointerType() - && !Type->isBlockPointerType() - && !Type->isFunctionType()) - return; + // Delay if this is not a function or pointer to block. + if (!Type->isFunctionPointerType() + && !Type->isBlockPointerType() + && !Type->isFunctionType()) + return true; - Type = S.Context.getNoReturnType(Type); + // Otherwise we can process right away. + Type = S.Context.getNoReturnType(Type); + return false; + } + + // Otherwise, a calling convention. + if (Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; + return false; + } + + QualType T = Type; + if (const PointerType *PT = Type->getAs<PointerType>()) + T = PT->getPointeeType(); + const FunctionType *Fn = T->getAs<FunctionType>(); + + // Delay if the type didn't work out to a function. + if (!Fn) return true; + + // TODO: diagnose uses of these conventions on the wrong target. + CallingConv CC; + switch (Attr.getKind()) { + case AttributeList::AT_cdecl: CC = CC_C; break; + case AttributeList::AT_fastcall: CC = CC_X86FastCall; break; + case AttributeList::AT_stdcall: CC = CC_X86StdCall; break; + default: llvm_unreachable("unexpected attribute kind"); return false; + } + + CallingConv CCOld = Fn->getCallConv(); + if (CC == CCOld) return false; + + if (CCOld != CC_Default) { + // Should we diagnose reapplications of the same convention? + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << FunctionType::getNameForCallConv(CC) + << FunctionType::getNameForCallConv(CCOld); + return false; + } + + // Diagnose the use of X86 fastcall on varargs or unprototyped functions. + if (CC == CC_X86FastCall) { + if (isa<FunctionNoProtoType>(Fn)) { + S.Diag(Attr.getLoc(), diag::err_cconv_knr) + << FunctionType::getNameForCallConv(CC); + return false; + } + + const FunctionProtoType *FnP = cast<FunctionProtoType>(Fn); + if (FnP->isVariadic()) { + S.Diag(Attr.getLoc(), diag::err_cconv_varargs) + << FunctionType::getNameForCallConv(CC); + return false; + } + } + + Type = S.Context.getCallConvType(Type, CC); + return false; } /// HandleVectorSizeAttribute - this attribute is only applicable to integral @@ -1705,10 +1825,12 @@ 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); + CurType = S.Context.getVectorType(CurType, vectorSize/typeSize, false, false); } -void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { +void ProcessTypeAttributeList(Sema &S, QualType &Result, + const AttributeList *AL, + DelayedAttributeSet &FnAttrs) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the // type, but others can be present in the type specifiers even though they @@ -1718,17 +1840,23 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { // the LeftOverAttrs list for rechaining. switch (AL->getKind()) { default: break; + case AttributeList::AT_address_space: - HandleAddressSpaceTypeAttribute(Result, *AL, *this); + HandleAddressSpaceTypeAttribute(Result, *AL, S); break; case AttributeList::AT_objc_gc: - HandleObjCGCTypeAttribute(Result, *AL, *this); - break; - case AttributeList::AT_noreturn: - HandleNoReturnTypeAttribute(Result, *AL, *this); + HandleObjCGCTypeAttribute(Result, *AL, S); break; case AttributeList::AT_vector_size: - HandleVectorSizeAttr(Result, *AL, *this); + HandleVectorSizeAttr(Result, *AL, S); + break; + + case AttributeList::AT_noreturn: + case AttributeList::AT_cdecl: + case AttributeList::AT_fastcall: + case AttributeList::AT_stdcall: + if (ProcessFnAttr(S, Result, *AL)) + FnAttrs.push_back(DelayedAttribute(AL, Result)); break; } } diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index 7c19bf6..d45d010 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -70,6 +70,48 @@ namespace { }; } +static void HandleX86ForceAlignArgPointerAttr(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 we try to apply it to a function pointer, warn. This is a special + // instance of the warn_attribute_ignored warning that can be turned + // off with -Wno-force-align-arg-pointer. + ValueDecl* VD = dyn_cast<ValueDecl>(D); + if (VD && VD->getType()->isFunctionPointerType()) { + S.Diag(Attr.getLoc(), diag::warn_faap_attribute_ignored); + return; + } + // Attribute can only be applied to function types. + if (!isa<FunctionDecl>(D)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr.getName() << /* function */0; + return; + } + + D->addAttr(::new (S.Context) X86ForceAlignArgPointerAttr()); +} + +namespace { + class X86AttributesSema : public TargetAttributesSema { + public: + X86AttributesSema() { } + bool ProcessDeclAttribute(Scope *scope, Decl *D, + const AttributeList &Attr, Sema &S) const { + if (Attr.getName()->getName() == "force_align_arg_pointer") { + HandleX86ForceAlignArgPointerAttr(D, Attr, S); + return true; + } + return false; + } + }; +} + const TargetAttributesSema &Sema::getTargetAttributesSema() const { if (TheTargetAttributesSema) return *TheTargetAttributesSema; @@ -81,6 +123,8 @@ const TargetAttributesSema &Sema::getTargetAttributesSema() const { case llvm::Triple::msp430: return *(TheTargetAttributesSema = new MSP430AttributesSema); + case llvm::Triple::x86: + return *(TheTargetAttributesSema = new X86AttributesSema); } } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index b2102af..fc069f7 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -428,7 +428,8 @@ 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); + QualType RebuildVectorType(QualType ElementType, unsigned NumElements, + bool IsAltiVec, bool IsPixel); /// \brief Build a new extended vector type given the element type and /// number of elements. @@ -524,9 +525,13 @@ public: /// and the given type. Subclasses may override this routine to provide /// different behavior. QualType RebuildTypenameType(NestedNameSpecifier *NNS, QualType T) { - if (NNS->isDependent()) - return SemaRef.Context.getTypenameType(NNS, + if (NNS->isDependent()) { + CXXScopeSpec SS; + SS.setScopeRep(NNS); + if (!SemaRef.computeDeclContext(SS)) + return SemaRef.Context.getTypenameType(NNS, cast<TemplateSpecializationType>(T)); + } return SemaRef.Context.getQualifiedNameType(NNS, T); } @@ -776,6 +781,28 @@ public: StartLoc, EndLoc)); } + /// \brief Build a new inline asm statement. + /// + /// By default, performs semantic analysis to build the new statement. + /// Subclasses may override this routine to provide different behavior. + OwningStmtResult RebuildAsmStmt(SourceLocation AsmLoc, + bool IsSimple, + bool IsVolatile, + unsigned NumOutputs, + unsigned NumInputs, + IdentifierInfo **Names, + MultiExprArg Constraints, + MultiExprArg Exprs, + ExprArg AsmString, + MultiExprArg Clobbers, + SourceLocation RParenLoc, + bool MSAsm) { + return getSema().ActOnAsmStmt(AsmLoc, IsSimple, IsVolatile, NumOutputs, + NumInputs, Names, move(Constraints), + move(Exprs), move(AsmString), move(Clobbers), + RParenLoc, MSAsm); + } + /// \brief Build a new C++ exception declaration. /// /// By default, performs semantic analysis to build the new decaration. @@ -1662,6 +1689,7 @@ Sema::OwningStmtResult TreeTransform<Derived>::TransformStmt(Stmt *S) { // Transform expressions by calling TransformExpr. #define STMT(Node, Parent) +#define ABSTRACT_EXPR(Node, Parent) #define EXPR(Node, Parent) case Stmt::Node##Class: #include "clang/AST/StmtNodes.def" { @@ -1685,6 +1713,7 @@ Sema::OwningExprResult TreeTransform<Derived>::TransformExpr(Expr *E) { switch (E->getStmtClass()) { case Stmt::NoStmtClass: break; #define STMT(Node, Parent) case Stmt::Node##Class: break; +#define ABSTRACT_EXPR(Node, Parent) #define EXPR(Node, Parent) \ case Stmt::Node##Class: return getDerived().Transform##Node(cast<Node>(E)); #include "clang/AST/StmtNodes.def" @@ -2448,7 +2477,8 @@ QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || ElementType != T->getElementType()) { - Result = getDerived().RebuildVectorType(ElementType, T->getNumElements()); + Result = getDerived().RebuildVectorType(ElementType, T->getNumElements(), + T->isAltiVec(), T->isPixel()); if (Result.isNull()) return QualType(); } @@ -3327,9 +3357,74 @@ TreeTransform<Derived>::TransformSwitchCase(SwitchCase *S) { template<typename Derived> Sema::OwningStmtResult TreeTransform<Derived>::TransformAsmStmt(AsmStmt *S) { - // FIXME: Implement! - assert(false && "Inline assembly cannot be transformed"); - return SemaRef.Owned(S->Retain()); + + ASTOwningVector<&ActionBase::DeleteExpr> Constraints(getSema()); + ASTOwningVector<&ActionBase::DeleteExpr> Exprs(getSema()); + llvm::SmallVector<IdentifierInfo *, 4> Names; + + OwningExprResult AsmString(SemaRef); + ASTOwningVector<&ActionBase::DeleteExpr> Clobbers(getSema()); + + bool ExprsChanged = false; + + // Go through the outputs. + for (unsigned I = 0, E = S->getNumOutputs(); I != E; ++I) { + Names.push_back(S->getOutputIdentifier(I)); + + // No need to transform the constraint literal. + Constraints.push_back(S->getOutputConstraintLiteral(I)->Retain()); + + // Transform the output expr. + Expr *OutputExpr = S->getOutputExpr(I); + OwningExprResult Result = getDerived().TransformExpr(OutputExpr); + if (Result.isInvalid()) + return SemaRef.StmtError(); + + ExprsChanged |= Result.get() != OutputExpr; + + Exprs.push_back(Result.takeAs<Expr>()); + } + + // Go through the inputs. + for (unsigned I = 0, E = S->getNumInputs(); I != E; ++I) { + Names.push_back(S->getInputIdentifier(I)); + + // No need to transform the constraint literal. + Constraints.push_back(S->getInputConstraintLiteral(I)->Retain()); + + // Transform the input expr. + Expr *InputExpr = S->getInputExpr(I); + OwningExprResult Result = getDerived().TransformExpr(InputExpr); + if (Result.isInvalid()) + return SemaRef.StmtError(); + + ExprsChanged |= Result.get() != InputExpr; + + Exprs.push_back(Result.takeAs<Expr>()); + } + + if (!getDerived().AlwaysRebuild() && !ExprsChanged) + return SemaRef.Owned(S->Retain()); + + // Go through the clobbers. + for (unsigned I = 0, E = S->getNumClobbers(); I != E; ++I) + Clobbers.push_back(S->getClobber(I)->Retain()); + + // No need to transform the asm string literal. + AsmString = SemaRef.Owned(S->getAsmString()); + + return getDerived().RebuildAsmStmt(S->getAsmLoc(), + S->isSimple(), + S->isVolatile(), + S->getNumOutputs(), + S->getNumInputs(), + Names.data(), + move_arg(Constraints), + move_arg(Exprs), + move(AsmString), + move_arg(Clobbers), + S->getRParenLoc(), + S->isMSAsm()); } @@ -3742,13 +3837,6 @@ TreeTransform<Derived>::TransformMemberExpr(MemberExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformCastExpr(CastExpr *E) { - assert(false && "Cannot transform abstract class"); - return SemaRef.Owned(E->Retain()); -} - -template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformBinaryOperator(BinaryOperator *E) { OwningExprResult LHS = getDerived().TransformExpr(E->getLHS()); if (LHS.isInvalid()) @@ -3812,13 +3900,6 @@ TreeTransform<Derived>::TransformImplicitCastExpr(ImplicitCastExpr *E) { template<typename Derived> Sema::OwningExprResult -TreeTransform<Derived>::TransformExplicitCastExpr(ExplicitCastExpr *E) { - assert(false && "Cannot transform abstract class"); - return SemaRef.Owned(E->Retain()); -} - -template<typename Derived> -Sema::OwningExprResult TreeTransform<Derived>::TransformCStyleCastExpr(CStyleCastExpr *E) { TypeSourceInfo *OldT; TypeSourceInfo *NewT; @@ -4433,7 +4514,7 @@ TreeTransform<Derived>::TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E) { if (!Param) return SemaRef.ExprError(); - if (getDerived().AlwaysRebuild() && + if (!getDerived().AlwaysRebuild() && Param == E->getParam()) return SemaRef.Owned(E->Retain()); @@ -4733,6 +4814,12 @@ TreeTransform<Derived>::TransformDependentScopeDeclRefExpr( template<typename Derived> Sema::OwningExprResult TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) { + // CXXConstructExprs are always implicit, so when we have a + // 1-argument construction we just transform that argument. + if (E->getNumArgs() == 1 || + (E->getNumArgs() > 1 && getDerived().DropCallArgument(E->getArg(1)))) + return getDerived().TransformExpr(E->getArg(0)); + TemporaryBase Rebase(*this, /*FIXME*/E->getLocStart(), DeclarationName()); QualType T = getDerived().TransformType(E->getType()); @@ -4784,6 +4871,16 @@ TreeTransform<Derived>::TransformCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { return getDerived().TransformExpr(E->getSubExpr()); } +/// \brief Transform a C++ reference-binding expression. +/// +/// Since CXXBindReferenceExpr nodes are implicitly generated, we just +/// transform the subexpression and return that. +template<typename Derived> +Sema::OwningExprResult +TreeTransform<Derived>::TransformCXXBindReferenceExpr(CXXBindReferenceExpr *E) { + return getDerived().TransformExpr(E->getSubExpr()); +} + /// \brief Transform a C++ expression that contains temporaries that should /// be destroyed after the expression is evaluated. /// @@ -5330,9 +5427,11 @@ TreeTransform<Derived>::RebuildDependentSizedArrayType(QualType ElementType, template<typename Derived> QualType TreeTransform<Derived>::RebuildVectorType(QualType ElementType, - unsigned NumElements) { + unsigned NumElements, + bool IsAltiVec, bool IsPixel) { // FIXME: semantic checking! - return SemaRef.Context.getVectorType(ElementType, NumElements); + return SemaRef.Context.getVectorType(ElementType, NumElements, + IsAltiVec, IsPixel); } template<typename Derived> @@ -5563,28 +5662,21 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, // Compute the transformed set of functions (and function templates) to be // used during overload resolution. - Sema::FunctionSet Functions; + UnresolvedSet<16> Functions; if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(CalleeExpr)) { assert(ULE->requiresADL()); // FIXME: Do we have to check // IsAcceptableNonMemberOperatorCandidate for each of these? - for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), - E = ULE->decls_end(); I != E; ++I) - Functions.insert(AnyFunctionDecl::getFromNamedDecl(*I)); + Functions.append(ULE->decls_begin(), ULE->decls_end()); } else { - Functions.insert(AnyFunctionDecl::getFromNamedDecl( - cast<DeclRefExpr>(CalleeExpr)->getDecl())); + Functions.addDecl(cast<DeclRefExpr>(CalleeExpr)->getDecl()); } // Add any functions found via argument-dependent lookup. Expr *Args[2] = { FirstExpr, SecondExpr }; unsigned NumArgs = 1 + (SecondExpr != 0); - DeclarationName OpName - = SemaRef.Context.DeclarationNames.getCXXOperatorName(Op); - SemaRef.ArgumentDependentLookup(OpName, /*Operator*/true, Args, NumArgs, - Functions); // Create the overloaded operator invocation for unary operators. if (NumArgs == 1 || isPostIncDec) { |