diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 47 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 9 |
2 files changed, 38 insertions, 18 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 109386db6b..28a637180a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10340,15 +10340,44 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { Func->setReferenced(); - // Don't mark this function as used multiple times, unless it's a constexpr - // function which we need to instantiate. - if (Func->isUsed(false) && - !(Func->isConstexpr() && !Func->getBody() && - Func->isImplicitlyInstantiable())) - return; - - if (!IsPotentiallyEvaluatedContext(*this)) - return; + // C++11 [basic.def.odr]p3: + // A function whose name appears as a potentially-evaluated expression is + // odr-used if it is the unique lookup result or the selected member of a + // set of overloaded functions [...]. + // + // We (incorrectly) mark overload resolution as an unevaluated context, so we + // can just check that here. Skip the rest of this function if we've already + // marked the function as used. + if (Func->isUsed(false) || !IsPotentiallyEvaluatedContext(*this)) { + // C++11 [temp.inst]p3: + // Unless a function template specialization has been explicitly + // instantiated or explicitly specialized, the function template + // specialization is implicitly instantiated when the specialization is + // referenced in a context that requires a function definition to exist. + // + // We consider constexpr function templates to be referenced in a context + // that requires a definition to exist whenever they are referenced. + // + // FIXME: This instantiates constexpr functions too frequently. If this is + // really an unevaluated context (and we're not just in the definition of a + // function template or overload resolution or other cases which we + // incorrectly consider to be unevaluated contexts), and we're not in a + // subexpression which we actually need to evaluate (for instance, a + // template argument, array bound or an expression in a braced-init-list), + // we are not permitted to instantiate this constexpr function definition. + // + // FIXME: This also implicitly defines special members too frequently. They + // are only supposed to be implicitly defined if they are odr-used, but they + // are not odr-used from constant expressions in unevaluated contexts. + // However, they cannot be referenced if they are deleted, and they are + // deleted whenever the implicit definition of the special member would + // fail. + if (!Func->isConstexpr() || Func->getBody()) + return; + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Func); + if (!Func->isImplicitlyInstantiable() && (!MD || MD->isUserProvided())) + return; + } // Note that this declaration has been used. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) { diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index a080031cdc..8e8580d701 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -2923,8 +2923,6 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType, case OR_Success: { // Record the standard conversion we used and the conversion function. CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); - S.MarkFunctionReferenced(From->getLocStart(), Constructor); - QualType ThisType = Constructor->getThisType(S.Context); // Initializer lists don't have conversions as such. User.Before.setAsIdentityConversion(); @@ -3105,8 +3103,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Best->Function)) { - S.MarkFunctionReferenced(From->getLocStart(), Constructor); - // C++ [over.ics.user]p1: // If the user-defined conversion is specified by a // constructor (12.3.1), the initial standard conversion @@ -3135,8 +3131,6 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(Best->Function)) { - S.MarkFunctionReferenced(From->getLocStart(), Conversion); - // C++ [over.ics.user]p1: // // [...] If the user-defined conversion is specified by a @@ -4049,8 +4043,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, if (!Best->FinalConversion.DirectBinding) return false; - if (Best->Function) - S.MarkFunctionReferenced(DeclLoc, Best->Function); ICS.setUserDefined(); ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; @@ -9225,7 +9217,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, Fn = Resolver.getMatchingFunctionDecl(); assert(Fn); FoundResult = *Resolver.getMatchingFunctionAccessPair(); - MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn); if (Complain) CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); } |