diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp | 593 |
1 files changed, 307 insertions, 286 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp index 0d7cbf4..3f6c6b0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclCXX.cpp @@ -162,34 +162,31 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, ExceptionSpecificationType EST = Proto->getExceptionSpecType(); + // If we have a throw-all spec at this point, ignore the function. + if (ComputedEST == EST_None) + return; + + switch(EST) { // If this function can throw any exceptions, make a note of that. - if (EST == EST_MSAny || EST == EST_None) { + case EST_MSAny: + case EST_None: ClearExceptions(); ComputedEST = EST; return; - } - // FIXME: If the call to this decl is using any of its default arguments, we // need to search them for potentially-throwing calls. - // If this function has a basic noexcept, it doesn't affect the outcome. - if (EST == EST_BasicNoexcept) - return; - - // If we have a throw-all spec at this point, ignore the function. - if (ComputedEST == EST_None) + case EST_BasicNoexcept: return; - // If we're still at noexcept(true) and there's a nothrow() callee, // change to that specification. - if (EST == EST_DynamicNone) { + case EST_DynamicNone: if (ComputedEST == EST_BasicNoexcept) ComputedEST = EST_DynamicNone; return; - } - // Check out noexcept specs. - if (EST == EST_ComputedNoexcept) { + case EST_ComputedNoexcept: + { FunctionProtoType::NoexceptResult NR = Proto->getNoexceptSpec(Self->Context); assert(NR != FunctionProtoType::NR_NoNoexcept && @@ -197,7 +194,6 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, assert(NR != FunctionProtoType::NR_Dependent && "Should not generate implicit declarations for dependent cases, " "and don't know how to handle them anyway."); - // noexcept(false) -> no spec on the new function if (NR == FunctionProtoType::NR_Throw) { ClearExceptions(); @@ -206,7 +202,9 @@ Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, // noexcept(true) won't change anything either. return; } - + default: + break; + } assert(EST == EST_Dynamic && "EST case not considered earlier."); assert(ComputedEST != EST_None && "Shouldn't collect exceptions when throw-all is guaranteed."); @@ -1232,9 +1230,9 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { Diag(Dcl->getLocation(), OK ? diag::warn_cxx11_compat_constexpr_body_no_return : diag::err_constexpr_body_no_return); - return OK; - } - if (ReturnStmts.size() > 1) { + if (!OK) + return false; + } else if (ReturnStmts.size() > 1) { Diag(ReturnStmts.back(), getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_constexpr_body_multiple_return @@ -1555,9 +1553,9 @@ NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, /// \brief Performs the actual work of attaching the given base class /// specifiers to a C++ class. -bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, - unsigned NumBases) { - if (NumBases == 0) +bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, + MutableArrayRef<CXXBaseSpecifier *> Bases) { + if (Bases.empty()) return false; // Used to keep track of which base types we have already seen, so @@ -1573,7 +1571,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, // Copy non-redundant base specifiers into permanent storage. unsigned NumGoodBases = 0; bool Invalid = false; - for (unsigned idx = 0; idx < NumBases; ++idx) { + for (unsigned idx = 0; idx < Bases.size(); ++idx) { QualType NewBaseType = Context.getCanonicalType(Bases[idx]->getType()); NewBaseType = NewBaseType.getLocalUnqualifiedType(); @@ -1599,7 +1597,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, Bases[NumGoodBases++] = Bases[idx]; // Note this base's direct & indirect bases, if there could be ambiguity. - if (NumBases > 1) + if (Bases.size() > 1) NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { @@ -1621,7 +1619,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, } // Attach the remaining base class specifiers to the derived class. - Class->setBases(Bases, NumGoodBases); + Class->setBases(Bases.data(), NumGoodBases); for (unsigned idx = 0; idx < NumGoodBases; ++idx) { // Check whether this direct base is inaccessible due to ambiguity. @@ -1656,21 +1654,21 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, /// ActOnBaseSpecifiers - Attach the given base specifiers to the /// class, after checking whether there are any duplicate base /// classes. -void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, CXXBaseSpecifier **Bases, - unsigned NumBases) { - if (!ClassDecl || !Bases || !NumBases) +void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, + MutableArrayRef<CXXBaseSpecifier *> Bases) { + if (!ClassDecl || Bases.empty()) return; AdjustDeclIfTemplate(ClassDecl); - AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases); + AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. -bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { if (!getLangOpts().CPlusPlus) return false; - + CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); if (!DerivedRD) return false; @@ -1684,13 +1682,18 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) return false; - // FIXME: instantiate DerivedRD if necessary. We need a PoI for this. - return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); + // FIXME: In a modules build, do we need the entire path to be visible for us + // to be able to use the inheritance relationship? + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + + return DerivedRD->isDerivedFrom(BaseRD); } /// \brief Determine whether the type \p Derived is a C++ class that is /// derived from the type \p Base. -bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { +bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base, + CXXBasePaths &Paths) { if (!getLangOpts().CPlusPlus) return false; @@ -1702,6 +1705,9 @@ bool Sema::IsDerivedFrom(QualType Derived, QualType Base, CXXBasePaths &Paths) { if (!BaseRD) return false; + if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) + return false; + return DerivedRD->isDerivedFrom(BaseRD, Paths); } @@ -1749,7 +1755,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, // explore multiple paths to determine if there is an ambiguity. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - bool DerivationOkay = IsDerivedFrom(Derived, Base, Paths); + bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(DerivationOkay && "Can only be used with a derived-to-base conversion"); (void)DerivationOkay; @@ -1783,7 +1789,7 @@ Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, // performance isn't as much of an issue. Paths.clear(); Paths.setRecordingPaths(true); - bool StillOkay = IsDerivedFrom(Derived, Base, Paths); + bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths); assert(StillOkay && "Can only be used with a derived-to-base conversion"); (void)StillOkay; @@ -2759,7 +2765,8 @@ static bool FindBaseInitializer(Sema &SemaRef, // virtual base class. CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, /*DetectVirtual=*/false); - if (SemaRef.IsDerivedFrom(SemaRef.Context.getTypeDeclType(ClassDecl), + if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(), + SemaRef.Context.getTypeDeclType(ClassDecl), BaseType, Paths)) { for (CXXBasePaths::paths_iterator Path = Paths.begin(); Path != Paths.end(); ++Path) { @@ -2982,10 +2989,15 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (BaseType.isNull()) { BaseType = Context.getTypeDeclType(TyD); MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); - if (SS.isSet()) - // FIXME: preserve source range information + if (SS.isSet()) { BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), BaseType); + TInfo = Context.CreateTypeSourceInfo(BaseType); + ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>(); + TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); + TL.setElaboratedKeywordLoc(SourceLocation()); + TL.setQualifierLoc(SS.getWithLocInContext(Context)); + } } } @@ -3483,7 +3495,8 @@ BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, MemberLookup, - /*TemplateArgs=*/nullptr); + /*TemplateArgs=*/nullptr, + /*S*/nullptr); if (CtorArg.isInvalid()) return true; @@ -4140,7 +4153,7 @@ static void DiagnoseBaseOrMemInitializerOrder( if (InitKey == IdealInitKeys[IdealIndex]) break; - assert(IdealIndex != NumIdealInits && + assert(IdealIndex < NumIdealInits && "initializer not found in initializer list"); } @@ -4407,64 +4420,35 @@ void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { } } -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - unsigned DiagID, AbstractDiagSelID SelID) { - class NonAbstractTypeDiagnoser : public TypeDiagnoser { - unsigned DiagID; - AbstractDiagSelID SelID; - - public: - NonAbstractTypeDiagnoser(unsigned DiagID, AbstractDiagSelID SelID) - : TypeDiagnoser(DiagID == 0), DiagID(DiagID), SelID(SelID) { } - - void diagnose(Sema &S, SourceLocation Loc, QualType T) override { - if (Suppressed) return; - if (SelID == -1) - S.Diag(Loc, DiagID) << T; - else - S.Diag(Loc, DiagID) << SelID << T; - } - } Diagnoser(DiagID, SelID); - - return RequireNonAbstractType(Loc, T, Diagnoser); -} - -bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, - TypeDiagnoser &Diagnoser) { +bool Sema::isAbstractType(SourceLocation Loc, QualType T) { if (!getLangOpts().CPlusPlus) return false; - if (const ArrayType *AT = Context.getAsArrayType(T)) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - - if (const PointerType *PT = T->getAs<PointerType>()) { - // Find the innermost pointer type. - while (const PointerType *T = PT->getPointeeType()->getAs<PointerType>()) - PT = T; - - if (const ArrayType *AT = Context.getAsArrayType(PT->getPointeeType())) - return RequireNonAbstractType(Loc, AT->getElementType(), Diagnoser); - } - - const RecordType *RT = T->getAs<RecordType>(); - if (!RT) + const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl(); + if (!RD) return false; - const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a + // class template specialization here, but doing so breaks a lot of code. // We can't answer whether something is abstract until it has a - // definition. If it's currently being defined, we'll walk back + // definition. If it's currently being defined, we'll walk back // over all the declarations when we have a full definition. const CXXRecordDecl *Def = RD->getDefinition(); if (!Def || Def->isBeingDefined()) return false; - if (!RD->isAbstract()) + return RD->isAbstract(); +} + +bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, + TypeDiagnoser &Diagnoser) { + if (!isAbstractType(Loc, T)) return false; + T = Context.getBaseElementType(T); Diagnoser.diagnose(*this, Loc, T); - DiagnoseAbstractType(RD); - + DiagnoseAbstractType(T->getAsCXXRecordDecl()); return true; } @@ -4684,6 +4668,60 @@ static void CheckAbstractClassUsage(AbstractUsageInfo &Info, } } +static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) { + Attr *ClassAttr = getDLLAttr(Class); + if (!ClassAttr) + return; + + assert(ClassAttr->getKind() == attr::DLLExport); + + TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); + + if (TSK == TSK_ExplicitInstantiationDeclaration) + // Don't go any further if this is just an explicit instantiation + // declaration. + return; + + for (Decl *Member : Class->decls()) { + auto *MD = dyn_cast<CXXMethodDecl>(Member); + if (!MD) + continue; + + if (Member->getAttr<DLLExportAttr>()) { + if (MD->isUserProvided()) { + // Instantiate non-default class member functions ... + + // .. except for certain kinds of template specializations. + if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) + continue; + + S.MarkFunctionReferenced(Class->getLocation(), MD); + + // The function will be passed to the consumer when its definition is + // encountered. + } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || + MD->isCopyAssignmentOperator() || + MD->isMoveAssignmentOperator()) { + // Synthesize and instantiate non-trivial implicit methods, explicitly + // defaulted methods, and the copy and move assignment operators. The + // latter are exported even if they are trivial, because the address of + // an operator can be taken and should compare equal accross libraries. + DiagnosticErrorTrap Trap(S.Diags); + S.MarkFunctionReferenced(Class->getLocation(), MD); + if (Trap.hasErrorOccurred()) { + S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) + << Class->getName() << !S.getLangOpts().CPlusPlus11; + break; + } + + // There is no later point when we will see the definition of this + // function, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + } + } + } +} + /// \brief Check class-level dllimport/dllexport attribute. void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { Attr *ClassAttr = getDLLAttr(Class); @@ -4785,45 +4823,10 @@ void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { NewAttr->setInherited(true); Member->addAttr(NewAttr); } - - if (MD && ClassExported) { - if (TSK == TSK_ExplicitInstantiationDeclaration) - // Don't go any further if this is just an explicit instantiation - // declaration. - continue; - - if (MD->isUserProvided()) { - // Instantiate non-default class member functions ... - - // .. except for certain kinds of template specializations. - if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) - continue; - - MarkFunctionReferenced(Class->getLocation(), MD); - - // The function will be passed to the consumer when its definition is - // encountered. - } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || - MD->isCopyAssignmentOperator() || - MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, explicitly - // defaulted methods, and the copy and move assignment operators. The - // latter are exported even if they are trivial, because the address of - // an operator can be taken and should compare equal accross libraries. - DiagnosticErrorTrap Trap(Diags); - MarkFunctionReferenced(Class->getLocation(), MD); - if (Trap.hasErrorOccurred()) { - Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) - << Class->getName() << !getLangOpts().CPlusPlus11; - break; - } - - // There is no later point when we will see the definition of this - // function, so pass it to the consumer now. - Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); - } - } } + + if (ClassExported) + DelayedDllExportClasses.push_back(Class); } /// \brief Perform propagation of DLL attributes from a derived class to a @@ -5623,7 +5626,9 @@ bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( /// having a particular direct or virtual base class. bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); - return shouldDeleteForClassSubobject(BaseClass, Base, 0); + // If program is correct, BaseClass cannot be null, but if it is, the error + // must be reported elsewhere. + return BaseClass && shouldDeleteForClassSubobject(BaseClass, Base, 0); } /// Check whether we should delete a special member function due to the class @@ -6270,77 +6275,75 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, return true; } -/// \brief Data used with FindHiddenVirtualMethod namespace { - struct FindHiddenVirtualMethodData { - Sema *S; - CXXMethodDecl *Method; - llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; - SmallVector<CXXMethodDecl *, 8> OverloadedMethods; - }; -} - -/// \brief Check whether any most overriden method from MD in Methods -static bool CheckMostOverridenMethods(const CXXMethodDecl *MD, - const llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) { - if (MD->size_overridden_methods() == 0) - return Methods.count(MD->getCanonicalDecl()); - for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), - E = MD->end_overridden_methods(); - I != E; ++I) - if (CheckMostOverridenMethods(*I, Methods)) - return true; - return false; -} +struct FindHiddenVirtualMethod { + Sema *S; + CXXMethodDecl *Method; + llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; + SmallVector<CXXMethodDecl *, 8> OverloadedMethods; -/// \brief Member lookup function that determines whether a given C++ -/// method overloads virtual methods in a base class without overriding any, -/// to be used with CXXRecordDecl::lookupInBases(). -static bool FindHiddenVirtualMethod(const CXXBaseSpecifier *Specifier, - CXXBasePath &Path, - void *UserData) { - RecordDecl *BaseRecord = Specifier->getType()->getAs<RecordType>()->getDecl(); - - FindHiddenVirtualMethodData &Data - = *static_cast<FindHiddenVirtualMethodData*>(UserData); - - DeclarationName Name = Data.Method->getDeclName(); - assert(Name.getNameKind() == DeclarationName::Identifier); - - bool foundSameNameMethod = false; - SmallVector<CXXMethodDecl *, 8> overloadedMethods; - for (Path.Decls = BaseRecord->lookup(Name); - !Path.Decls.empty(); - Path.Decls = Path.Decls.slice(1)) { - NamedDecl *D = Path.Decls.front(); - if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { - MD = MD->getCanonicalDecl(); - foundSameNameMethod = true; - // Interested only in hidden virtual methods. - if (!MD->isVirtual()) - continue; - // If the method we are checking overrides a method from its base - // don't warn about the other overloaded methods. Clang deviates from GCC - // by only diagnosing overloads of inherited virtual functions that do not - // override any other virtual functions in the base. GCC's - // -Woverloaded-virtual diagnoses any derived function hiding a virtual - // function from a base class. These cases may be better served by a - // warning (not specific to virtual functions) on call sites when the call - // would select a different function from the base class, were it visible. - // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. - if (!Data.S->IsOverload(Data.Method, MD, false)) +private: + /// Check whether any most overriden method from MD in Methods + static bool CheckMostOverridenMethods( + const CXXMethodDecl *MD, + const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) { + if (MD->size_overridden_methods() == 0) + return Methods.count(MD->getCanonicalDecl()); + for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(), + E = MD->end_overridden_methods(); + I != E; ++I) + if (CheckMostOverridenMethods(*I, Methods)) return true; - // Collect the overload only if its hidden. - if (!CheckMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods)) - overloadedMethods.push_back(MD); - } + return false; } - if (foundSameNameMethod) - Data.OverloadedMethods.append(overloadedMethods.begin(), - overloadedMethods.end()); - return foundSameNameMethod; -} +public: + /// Member lookup function that determines whether a given C++ + /// method overloads virtual methods in a base class without overriding any, + /// to be used with CXXRecordDecl::lookupInBases(). + bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { + RecordDecl *BaseRecord = + Specifier->getType()->getAs<RecordType>()->getDecl(); + + DeclarationName Name = Method->getDeclName(); + assert(Name.getNameKind() == DeclarationName::Identifier); + + bool foundSameNameMethod = false; + SmallVector<CXXMethodDecl *, 8> overloadedMethods; + for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); + Path.Decls = Path.Decls.slice(1)) { + NamedDecl *D = Path.Decls.front(); + if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + MD = MD->getCanonicalDecl(); + foundSameNameMethod = true; + // Interested only in hidden virtual methods. + if (!MD->isVirtual()) + continue; + // If the method we are checking overrides a method from its base + // don't warn about the other overloaded methods. Clang deviates from + // GCC by only diagnosing overloads of inherited virtual functions that + // do not override any other virtual functions in the base. GCC's + // -Woverloaded-virtual diagnoses any derived function hiding a virtual + // function from a base class. These cases may be better served by a + // warning (not specific to virtual functions) on call sites when the + // call would select a different function from the base class, were it + // visible. + // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. + if (!S->IsOverload(Method, MD, false)) + return true; + // Collect the overload only if its hidden. + if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods)) + overloadedMethods.push_back(MD); + } + } + + if (foundSameNameMethod) + OverloadedMethods.append(overloadedMethods.begin(), + overloadedMethods.end()); + return foundSameNameMethod; + } +}; +} // end anonymous namespace /// \brief Add the most overriden methods from MD to Methods static void AddMostOverridenMethods(const CXXMethodDecl *MD, @@ -6363,9 +6366,9 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. /*bool RecordPaths=*/false, /*bool DetectVirtual=*/false); - FindHiddenVirtualMethodData Data; - Data.Method = MD; - Data.S = this; + FindHiddenVirtualMethod FHVM; + FHVM.Method = MD; + FHVM.S = this; // Keep the base methods that were overriden or introduced in the subclass // by 'using' in a set. A base method not in this set is hidden. @@ -6376,11 +6379,11 @@ void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I)) ND = shad->getTargetDecl(); if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) - AddMostOverridenMethods(MD, Data.OverridenAndUsingBaseMethods); + AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods); } - if (DC->lookupInBases(&FindHiddenVirtualMethod, &Data, Paths)) - OverloadedMethods = Data.OverloadedMethods; + if (DC->lookupInBases(FHVM, Paths)) + OverloadedMethods = FHVM.OverloadedMethods; } void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, @@ -6897,7 +6900,7 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, return Context.getFunctionType(Context.VoidTy, None, EPI); } -static void extendLeft(SourceRange &R, const SourceRange &Before) { +static void extendLeft(SourceRange &R, SourceRange Before) { if (Before.isInvalid()) return; R.setBegin(Before.getBegin()); @@ -6905,7 +6908,7 @@ static void extendLeft(SourceRange &R, const SourceRange &Before) { R.setEnd(Before.getEnd()); } -static void extendRight(SourceRange &R, const SourceRange &After) { +static void extendRight(SourceRange &R, SourceRange After) { if (After.isInvalid()) return; if (R.getBegin().isInvalid()) @@ -7019,7 +7022,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, // If we can provide a correct fix-it hint, do so. if (After.isInvalid() && ConvTSI) { SourceLocation InsertLoc = - PP.getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); + getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); DB << FixItHint::CreateInsertion(InsertLoc, " ") << FixItHint::CreateInsertionFromRange( InsertLoc, CharSourceRange::getTokenRange(Before)) @@ -7102,7 +7105,7 @@ Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { if (ConvType == ClassType) Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) << ClassType; - else if (IsDerivedFrom(ClassType, ConvType)) + else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType)) Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) << ClassType << ConvType; } else if (ConvType->isVoidType()) { @@ -7169,7 +7172,8 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, - AttributeList *AttrList) { + AttributeList *AttrList, + UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -7190,23 +7194,14 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // treated as an original-namespace-name. // // Since namespace names are unique in their scope, and we don't - // look through using directives, just look for any ordinary names. - - const unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Member | - Decl::IDNS_Type | Decl::IDNS_Using | Decl::IDNS_Tag | - Decl::IDNS_Namespace; - NamedDecl *PrevDecl = nullptr; - DeclContext::lookup_result R = CurContext->getRedeclContext()->lookup(II); - for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; - ++I) { - if ((*I)->getIdentifierNamespace() & IDNS) { - PrevDecl = *I; - break; - } - } - + // look through using directives, just look for any ordinary names + // as if by qualified name lookup. + LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, ForRedeclaration); + LookupQualifiedName(R, CurContext->getRedeclContext()); + NamedDecl *PrevDecl = + R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); - + if (PrevNS) { // This is an extended namespace definition. if (IsInline != PrevNS->isInline()) @@ -7293,14 +7288,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // namespace internal linkage. if (!PrevNS) { - UsingDirectiveDecl* UD - = UsingDirectiveDecl::Create(Context, Parent, - /* 'using' */ LBrace, - /* 'namespace' */ SourceLocation(), - /* qualifier */ NestedNameSpecifierLoc(), - /* identifier */ SourceLocation(), - Namespc, - /* Ancestor */ Parent); + UD = UsingDirectiveDecl::Create(Context, Parent, + /* 'using' */ LBrace, + /* 'namespace' */ SourceLocation(), + /* qualifier */ NestedNameSpecifierLoc(), + /* identifier */ SourceLocation(), + Namespc, + /* Ancestor */ Parent); UD->setImplicit(); Parent->addDecl(UD); } @@ -7538,7 +7532,7 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, S.PDiag(diag::err_using_directive_suggest) << Ident, S.PDiag(diag::note_namespace_defined_here)); } - R.addDecl(Corrected.getCorrectionDecl()); + R.addDecl(Corrected.getFoundDecl()); return true; } return false; @@ -7556,7 +7550,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, assert(IdentLoc.isValid() && "Invalid NamespceName location."); // This can only happen along a recovery path. - while (S->getFlags() & Scope::TemplateParamScope) + while (S->isTemplateParamScope()) S = S->getParent(); assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); @@ -7586,9 +7580,9 @@ Decl *Sema::ActOnUsingDirective(Scope *S, } if (!R.empty()) { - NamedDecl *Named = R.getFoundDecl(); - assert((isa<NamespaceDecl>(Named) || isa<NamespaceAliasDecl>(Named)) - && "expected namespace decl"); + NamedDecl *Named = R.getRepresentativeDecl(); + NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>(); + assert(NS && "expected namespace decl"); // The use of a nested name specifier may trigger deprecation warnings. DiagnoseUseOfDecl(Named, IdentLoc); @@ -7605,7 +7599,6 @@ Decl *Sema::ActOnUsingDirective(Scope *S, // Find enclosing context containing both using-directive and // nominated namespace. - NamespaceDecl *NS = getNamespaceDecl(Named); DeclContext *CommonAncestor = cast<DeclContext>(NS); while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) CommonAncestor = CommonAncestor->getParent(); @@ -7805,7 +7798,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, FoundEquivalentDecl = true; } - (isa<TagDecl>(D) ? Tag : NonTag) = D; + if (isVisible(D)) + (isa<TagDecl>(D) ? Tag : NonTag) = D; } if (FoundEquivalentDecl) @@ -8014,6 +8008,10 @@ public: // FIXME: Check that the base class member is accessible? } + } else { + auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND); + if (FoundRecord && FoundRecord->isInjectedClassName()) + return false; } if (isa<TypeDecl>(ND)) @@ -8377,7 +8375,7 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, } else { // Convert 'using X::Y;' to 'typedef X::Y Y;'. SourceLocation InsertLoc = - PP.getLocForEndOfToken(NameInfo.getLocEnd()); + getLocForEndOfToken(NameInfo.getLocEnd()); Diag(InsertLoc, diag::note_using_decl_class_member_workaround) << 1 // typedef declaration << FixItHint::CreateReplacement(UsingLoc, "typedef") @@ -8470,40 +8468,26 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, // in the UsingDecl and UsingShadowDecl so that these checks didn't // need to be repeated. - struct UserData { - llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases; - - static bool collect(const CXXRecordDecl *Base, void *OpaqueData) { - UserData *Data = reinterpret_cast<UserData*>(OpaqueData); - Data->Bases.insert(Base); - return true; - } - - bool hasDependentBases(const CXXRecordDecl *Class) { - return !Class->forallBases(collect, this); - } - - /// Returns true if the base is dependent or is one of the - /// accumulated base classes. - static bool doesNotContain(const CXXRecordDecl *Base, void *OpaqueData) { - UserData *Data = reinterpret_cast<UserData*>(OpaqueData); - return !Data->Bases.count(Base); - } - - bool mightShareBases(const CXXRecordDecl *Class) { - return Bases.count(Class) || !Class->forallBases(doesNotContain, this); - } + llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases; + auto Collect = [&Bases](const CXXRecordDecl *Base) { + Bases.insert(Base); + return true; }; - UserData Data; - - // Returns false if we find a dependent base. - if (Data.hasDependentBases(cast<CXXRecordDecl>(CurContext))) + // Collect all bases. Return false if we find a dependent base. + if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect)) return false; - // Returns false if the class has a dependent base or if it or one + // Returns true if the base is dependent or is one of the accumulated base + // classes. + auto IsNotBase = [&Bases](const CXXRecordDecl *Base) { + return !Bases.count(Base); + }; + + // Return false if the class has a dependent base or if it or one // of its bases is present in the base set of the current context. - if (Data.mightShareBases(cast<CXXRecordDecl>(NamedContext))) + if (Bases.count(cast<CXXRecordDecl>(NamedContext)) || + !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase)) return false; Diag(SS.getRange().getBegin(), @@ -8524,7 +8508,7 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. - while (S->getFlags() & Scope::TemplateParamScope) + while (S->isTemplateParamScope()) S = S->getParent(); assert((S->getFlags() & Scope::DeclScope) && "got alias-declaration outside of declaration scope"); @@ -8685,28 +8669,41 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, } } assert(!R.isAmbiguous() && !R.empty()); + NamedDecl *ND = R.getRepresentativeDecl(); // Check if we have a previous declaration with the same name. - NamedDecl *PrevDecl = LookupSingleName(S, Alias, AliasLoc, LookupOrdinaryName, - ForRedeclaration); - if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) - PrevDecl = nullptr; + LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, + ForRedeclaration); + LookupName(PrevR, S); - NamedDecl *ND = R.getFoundDecl(); + // Check we're not shadowing a template parameter. + if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl()); + PrevR.clear(); + } - if (PrevDecl) { + // Filter out any other lookup result from an enclosing scope. + FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false, + /*AllowInlineNamespace*/false); + + // Find the previous declaration and check that we can redeclare it. + NamespaceAliasDecl *Prev = nullptr; + if (PrevR.isSingleResult()) { + NamedDecl *PrevDecl = PrevR.getRepresentativeDecl(); if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { // We already have an alias with the same name that points to the same // namespace; check that it matches. - if (!AD->getNamespace()->Equals(getNamespaceDecl(ND))) { + if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) { + Prev = AD; + } else if (isVisible(PrevDecl)) { Diag(AliasLoc, diag::err_redefinition_different_namespace_alias) << Alias; - Diag(PrevDecl->getLocation(), diag::note_previous_namespace_alias) + Diag(AD->getLocation(), diag::note_previous_namespace_alias) << AD->getNamespace(); return nullptr; } - } else { - unsigned DiagID = isa<NamespaceDecl>(PrevDecl) + } else if (isVisible(PrevDecl)) { + unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl()) ? diag::err_redefinition : diag::err_redefinition_different_kind; Diag(AliasLoc, DiagID) << Alias; @@ -8722,8 +8719,8 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, Alias, SS.getWithLocInContext(Context), IdentLoc, ND); - if (PrevDecl) - AliasDecl->setPreviousDecl(cast<NamespaceAliasDecl>(PrevDecl)); + if (Prev) + AliasDecl->setPreviousDecl(Prev); PushOnScopeChains(AliasDecl, S); return AliasDecl; @@ -9497,7 +9494,7 @@ static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) { } } -void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) { +void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { auto *RD = dyn_cast<CXXRecordDecl>(D); // Default constructors that are annotated with __declspec(dllexport) which @@ -9505,6 +9502,15 @@ void Sema::ActOnFinishCXXMemberDefaultArgs(Decl *D) { // wrapped with a thunk called the default constructor closure. if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft()) getDefaultArgExprsForConstructors(*this, RD); + + if (!DelayedDllExportClasses.empty()) { + // Calling ReferenceDllExportedMethods might cause the current function to + // be called again, so use a local copy of DelayedDllExportClasses. + SmallVector<CXXRecordDecl *, 4> WorkList; + std::swap(DelayedDllExportClasses, WorkList); + for (CXXRecordDecl *Class : WorkList) + ReferenceDllExportedMethods(*this, Class); + } } void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, @@ -9618,7 +9624,7 @@ public: Expr *build(Sema &S, SourceLocation Loc) const override { return assertNotNull(S.BuildMemberReferenceExpr( Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), - nullptr, MemberLookup, nullptr).get()); + nullptr, MemberLookup, nullptr, nullptr).get()); } MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow, @@ -9828,7 +9834,7 @@ buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, SS, /*TemplateKWLoc=*/SourceLocation(), /*FirstQualifierInScope=*/nullptr, OpLookup, - /*TemplateArgs=*/nullptr, + /*TemplateArgs=*/nullptr, /*S*/nullptr, /*SuppressQualifierCheck=*/true); if (OpEqualRef.isInvalid()) return StmtError(); @@ -12207,7 +12213,7 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, diag::ext_unelaborated_friend_type) << (unsigned) RD->getTagKind() << T - << FixItHint::CreateInsertion(PP.getLocForEndOfToken(FriendLoc), + << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc), InsertionText); } else { Diag(FriendLoc, @@ -12673,15 +12679,30 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, DC = CurContext; assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); } - + if (!DC->isRecord()) { + int DiagArg = -1; + switch (D.getName().getKind()) { + case UnqualifiedId::IK_ConstructorTemplateId: + case UnqualifiedId::IK_ConstructorName: + DiagArg = 0; + break; + case UnqualifiedId::IK_DestructorName: + DiagArg = 1; + break; + case UnqualifiedId::IK_ConversionFunctionId: + DiagArg = 2; + break; + case UnqualifiedId::IK_Identifier: + case UnqualifiedId::IK_ImplicitSelfParam: + case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedId::IK_TemplateId: + break; + } // This implies that it has to be an operator or function. - if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName || - D.getName().getKind() == UnqualifiedId::IK_DestructorName || - D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) { - Diag(Loc, diag::err_introducing_special_friend) << - (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 : - D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2); + if (DiagArg >= 0) { + Diag(Loc, diag::err_introducing_special_friend) << DiagArg; return nullptr; } } @@ -12983,7 +13004,7 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { // Check if the new class derives from the old class. - if (!IsDerivedFrom(NewClassTy, OldClassTy)) { + if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) { Diag(New->getLocation(), diag::err_covariant_return_not_derived) << New->getDeclName() << NewTy << OldTy << New->getReturnTypeSourceRange(); |