| //===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements semantic analysis for C++ declarations. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/AST/ASTConsumer.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/ASTLambda.h" |
| #include "clang/AST/ASTMutationListener.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/CharUnits.h" |
| #include "clang/AST/ComparisonCategories.h" |
| #include "clang/AST/EvaluatedExprVisitor.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/RecordLayout.h" |
| #include "clang/AST/RecursiveASTVisitor.h" |
| #include "clang/AST/StmtVisitor.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/AST/TypeOrdering.h" |
| #include "clang/Basic/AttributeCommonInfo.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Lex/LiteralSupport.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Sema/CXXFieldCollector.h" |
| #include "clang/Sema/DeclSpec.h" |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/ParsedTemplate.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/ScopeInfo.h" |
| #include "clang/Sema/SemaInternal.h" |
| #include "clang/Sema/Template.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/StringExtras.h" |
| #include <map> |
| #include <set> |
| |
| using namespace clang; |
| |
| //===----------------------------------------------------------------------===// |
| // CheckDefaultArgumentVisitor |
| //===----------------------------------------------------------------------===// |
| |
| namespace { |
| /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses |
| /// the default argument of a parameter to determine whether it |
| /// contains any ill-formed subexpressions. For example, this will |
| /// diagnose the use of local variables or parameters within the |
| /// default argument expression. |
| class CheckDefaultArgumentVisitor |
| : public StmtVisitor<CheckDefaultArgumentVisitor, bool> { |
| Expr *DefaultArg; |
| Sema *S; |
| |
| public: |
| CheckDefaultArgumentVisitor(Expr *defarg, Sema *s) |
| : DefaultArg(defarg), S(s) {} |
| |
| bool VisitExpr(Expr *Node); |
| bool VisitDeclRefExpr(DeclRefExpr *DRE); |
| bool VisitCXXThisExpr(CXXThisExpr *ThisE); |
| bool VisitLambdaExpr(LambdaExpr *Lambda); |
| bool VisitPseudoObjectExpr(PseudoObjectExpr *POE); |
| }; |
| |
| /// VisitExpr - Visit all of the children of this expression. |
| bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) { |
| bool IsInvalid = false; |
| for (Stmt *SubStmt : Node->children()) |
| IsInvalid |= Visit(SubStmt); |
| return IsInvalid; |
| } |
| |
| /// VisitDeclRefExpr - Visit a reference to a declaration, to |
| /// determine whether this declaration can be used in the default |
| /// argument expression. |
| bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) { |
| NamedDecl *Decl = DRE->getDecl(); |
| if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) { |
| // C++ [dcl.fct.default]p9 |
| // Default arguments are evaluated each time the function is |
| // called. The order of evaluation of function arguments is |
| // unspecified. Consequently, parameters of a function shall not |
| // be used in default argument expressions, even if they are not |
| // evaluated. Parameters of a function declared before a default |
| // argument expression are in scope and can hide namespace and |
| // class member names. |
| return S->Diag(DRE->getBeginLoc(), |
| diag::err_param_default_argument_references_param) |
| << Param->getDeclName() << DefaultArg->getSourceRange(); |
| } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) { |
| // C++ [dcl.fct.default]p7 |
| // Local variables shall not be used in default argument |
| // expressions. |
| if (VDecl->isLocalVarDecl()) |
| return S->Diag(DRE->getBeginLoc(), |
| diag::err_param_default_argument_references_local) |
| << VDecl->getDeclName() << DefaultArg->getSourceRange(); |
| } |
| |
| return false; |
| } |
| |
| /// VisitCXXThisExpr - Visit a C++ "this" expression. |
| bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) { |
| // C++ [dcl.fct.default]p8: |
| // The keyword this shall not be used in a default argument of a |
| // member function. |
| return S->Diag(ThisE->getBeginLoc(), |
| diag::err_param_default_argument_references_this) |
| << ThisE->getSourceRange(); |
| } |
| |
| bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) { |
| bool Invalid = false; |
| for (PseudoObjectExpr::semantics_iterator |
| i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) { |
| Expr *E = *i; |
| |
| // Look through bindings. |
| if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { |
| E = OVE->getSourceExpr(); |
| assert(E && "pseudo-object binding without source expression?"); |
| } |
| |
| Invalid |= Visit(E); |
| } |
| return Invalid; |
| } |
| |
| bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) { |
| // C++11 [expr.lambda.prim]p13: |
| // A lambda-expression appearing in a default argument shall not |
| // implicitly or explicitly capture any entity. |
| if (Lambda->capture_begin() == Lambda->capture_end()) |
| return false; |
| |
| return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg); |
| } |
| } |
| |
| void |
| Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc, |
| const CXXMethodDecl *Method) { |
| // If we have an MSAny spec already, don't bother. |
| if (!Method || ComputedEST == EST_MSAny) |
| return; |
| |
| const FunctionProtoType *Proto |
| = Method->getType()->getAs<FunctionProtoType>(); |
| Proto = Self->ResolveExceptionSpec(CallLoc, Proto); |
| if (!Proto) |
| return; |
| |
| ExceptionSpecificationType EST = Proto->getExceptionSpecType(); |
| |
| // If we have a throw-all spec at this point, ignore the function. |
| if (ComputedEST == EST_None) |
| return; |
| |
| if (EST == EST_None && Method->hasAttr<NoThrowAttr>()) |
| EST = EST_BasicNoexcept; |
| |
| switch (EST) { |
| case EST_Unparsed: |
| case EST_Uninstantiated: |
| case EST_Unevaluated: |
| llvm_unreachable("should not see unresolved exception specs here"); |
| |
| // If this function can throw any exceptions, make a note of that. |
| case EST_MSAny: |
| case EST_None: |
| // FIXME: Whichever we see last of MSAny and None determines our result. |
| // We should make a consistent, order-independent choice here. |
| ClearExceptions(); |
| ComputedEST = EST; |
| return; |
| case EST_NoexceptFalse: |
| ClearExceptions(); |
| ComputedEST = EST_None; |
| 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. |
| case EST_BasicNoexcept: |
| case EST_NoexceptTrue: |
| case EST_NoThrow: |
| return; |
| // If we're still at noexcept(true) and there's a throw() callee, |
| // change to that specification. |
| case EST_DynamicNone: |
| if (ComputedEST == EST_BasicNoexcept) |
| ComputedEST = EST_DynamicNone; |
| return; |
| case EST_DependentNoexcept: |
| llvm_unreachable( |
| "should not generate implicit declarations for dependent cases"); |
| case EST_Dynamic: |
| break; |
| } |
| assert(EST == EST_Dynamic && "EST case not considered earlier."); |
| assert(ComputedEST != EST_None && |
| "Shouldn't collect exceptions when throw-all is guaranteed."); |
| ComputedEST = EST_Dynamic; |
| // Record the exceptions in this function's exception specification. |
| for (const auto &E : Proto->exceptions()) |
| if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)).second) |
| Exceptions.push_back(E); |
| } |
| |
| void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) { |
| if (!E || ComputedEST == EST_MSAny) |
| return; |
| |
| // FIXME: |
| // |
| // C++0x [except.spec]p14: |
| // [An] implicit exception-specification specifies the type-id T if and |
| // only if T is allowed by the exception-specification of a function directly |
| // invoked by f's implicit definition; f shall allow all exceptions if any |
| // function it directly invokes allows all exceptions, and f shall allow no |
| // exceptions if every function it directly invokes allows no exceptions. |
| // |
| // Note in particular that if an implicit exception-specification is generated |
| // for a function containing a throw-expression, that specification can still |
| // be noexcept(true). |
| // |
| // Note also that 'directly invoked' is not defined in the standard, and there |
| // is no indication that we should only consider potentially-evaluated calls. |
| // |
| // Ultimately we should implement the intent of the standard: the exception |
| // specification should be the set of exceptions which can be thrown by the |
| // implicit definition. For now, we assume that any non-nothrow expression can |
| // throw any exception. |
| |
| if (Self->canThrow(E)) |
| ComputedEST = EST_None; |
| } |
| |
| bool |
| Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg, |
| SourceLocation EqualLoc) { |
| if (RequireCompleteType(Param->getLocation(), Param->getType(), |
| diag::err_typecheck_decl_incomplete_type)) { |
| Param->setInvalidDecl(); |
| return true; |
| } |
| |
| // C++ [dcl.fct.default]p5 |
| // A default argument expression is implicitly converted (clause |
| // 4) to the parameter type. The default argument expression has |
| // the same semantic constraints as the initializer expression in |
| // a declaration of a variable of the parameter type, using the |
| // copy-initialization semantics (8.5). |
| InitializedEntity Entity = InitializedEntity::InitializeParameter(Context, |
| Param); |
| InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(), |
| EqualLoc); |
| InitializationSequence InitSeq(*this, Entity, Kind, Arg); |
| ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg); |
| if (Result.isInvalid()) |
| return true; |
| Arg = Result.getAs<Expr>(); |
| |
| CheckCompletedExpr(Arg, EqualLoc); |
| Arg = MaybeCreateExprWithCleanups(Arg); |
| |
| // Okay: add the default argument to the parameter |
| Param->setDefaultArg(Arg); |
| |
| // We have already instantiated this parameter; provide each of the |
| // instantiations with the uninstantiated default argument. |
| UnparsedDefaultArgInstantiationsMap::iterator InstPos |
| = UnparsedDefaultArgInstantiations.find(Param); |
| if (InstPos != UnparsedDefaultArgInstantiations.end()) { |
| for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I) |
| InstPos->second[I]->setUninstantiatedDefaultArg(Arg); |
| |
| // We're done tracking this parameter's instantiations. |
| UnparsedDefaultArgInstantiations.erase(InstPos); |
| } |
| |
| return false; |
| } |
| |
| /// ActOnParamDefaultArgument - Check whether the default argument |
| /// provided for a function parameter is well-formed. If so, attach it |
| /// to the parameter declaration. |
| void |
| Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, |
| Expr *DefaultArg) { |
| if (!param || !DefaultArg) |
| return; |
| |
| ParmVarDecl *Param = cast<ParmVarDecl>(param); |
| UnparsedDefaultArgLocs.erase(Param); |
| |
| // Default arguments are only permitted in C++ |
| if (!getLangOpts().CPlusPlus) { |
| Diag(EqualLoc, diag::err_param_default_argument) |
| << DefaultArg->getSourceRange(); |
| Param->setInvalidDecl(); |
| return; |
| } |
| |
| // Check for unexpanded parameter packs. |
| if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) { |
| Param->setInvalidDecl(); |
| return; |
| } |
| |
| // C++11 [dcl.fct.default]p3 |
| // A default argument expression [...] shall not be specified for a |
| // parameter pack. |
| if (Param->isParameterPack()) { |
| Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack) |
| << DefaultArg->getSourceRange(); |
| return; |
| } |
| |
| // Check that the default argument is well-formed |
| CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this); |
| if (DefaultArgChecker.Visit(DefaultArg)) { |
| Param->setInvalidDecl(); |
| return; |
| } |
| |
| SetParamDefaultArgument(Param, DefaultArg, EqualLoc); |
| } |
| |
| /// ActOnParamUnparsedDefaultArgument - We've seen a default |
| /// argument for a function parameter, but we can't parse it yet |
| /// because we're inside a class definition. Note that this default |
| /// argument will be parsed later. |
| void Sema::ActOnParamUnparsedDefaultArgument(Decl *param, |
| SourceLocation EqualLoc, |
| SourceLocation ArgLoc) { |
| if (!param) |
| return; |
| |
| ParmVarDecl *Param = cast<ParmVarDecl>(param); |
| Param->setUnparsedDefaultArg(); |
| UnparsedDefaultArgLocs[Param] = ArgLoc; |
| } |
| |
| /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of |
| /// the default argument for the parameter param failed. |
| void Sema::ActOnParamDefaultArgumentError(Decl *param, |
| SourceLocation EqualLoc) { |
| if (!param) |
| return; |
| |
| ParmVarDecl *Param = cast<ParmVarDecl>(param); |
| Param->setInvalidDecl(); |
| UnparsedDefaultArgLocs.erase(Param); |
| Param->setDefaultArg(new(Context) |
| OpaqueValueExpr(EqualLoc, |
| Param->getType().getNonReferenceType(), |
| VK_RValue)); |
| } |
| |
| /// CheckExtraCXXDefaultArguments - Check for any extra default |
| /// arguments in the declarator, which is not a function declaration |
| /// or definition and therefore is not permitted to have default |
| /// arguments. This routine should be invoked for every declarator |
| /// that is not a function declaration or definition. |
| void Sema::CheckExtraCXXDefaultArguments(Declarator &D) { |
| // C++ [dcl.fct.default]p3 |
| // A default argument expression shall be specified only in the |
| // parameter-declaration-clause of a function declaration or in a |
| // template-parameter (14.1). It shall not be specified for a |
| // parameter pack. If it is specified in a |
| // parameter-declaration-clause, it shall not occur within a |
| // declarator or abstract-declarator of a parameter-declaration. |
| bool MightBeFunction = D.isFunctionDeclarationContext(); |
| for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) { |
| DeclaratorChunk &chunk = D.getTypeObject(i); |
| if (chunk.Kind == DeclaratorChunk::Function) { |
| if (MightBeFunction) { |
| // This is a function declaration. It can have default arguments, but |
| // keep looking in case its return type is a function type with default |
| // arguments. |
| MightBeFunction = false; |
| continue; |
| } |
| for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e; |
| ++argIdx) { |
| ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param); |
| if (Param->hasUnparsedDefaultArg()) { |
| std::unique_ptr<CachedTokens> Toks = |
| std::move(chunk.Fun.Params[argIdx].DefaultArgTokens); |
| SourceRange SR; |
| if (Toks->size() > 1) |
| SR = SourceRange((*Toks)[1].getLocation(), |
| Toks->back().getLocation()); |
| else |
| SR = UnparsedDefaultArgLocs[Param]; |
| Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) |
| << SR; |
| } else if (Param->getDefaultArg()) { |
| Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) |
| << Param->getDefaultArg()->getSourceRange(); |
| Param->setDefaultArg(nullptr); |
| } |
| } |
| } else if (chunk.Kind != DeclaratorChunk::Paren) { |
| MightBeFunction = false; |
| } |
| } |
| } |
| |
| static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) { |
| for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) { |
| const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1); |
| if (!PVD->hasDefaultArg()) |
| return false; |
| if (!PVD->hasInheritedDefaultArg()) |
| return true; |
| } |
| return false; |
| } |
| |
| /// MergeCXXFunctionDecl - Merge two declarations of the same C++ |
| /// function, once we already know that they have the same |
| /// type. Subroutine of MergeFunctionDecl. Returns true if there was an |
| /// error, false otherwise. |
| bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, |
| Scope *S) { |
| bool Invalid = false; |
| |
| // The declaration context corresponding to the scope is the semantic |
| // parent, unless this is a local function declaration, in which case |
| // it is that surrounding function. |
| DeclContext *ScopeDC = New->isLocalExternDecl() |
| ? New->getLexicalDeclContext() |
| : New->getDeclContext(); |
| |
| // Find the previous declaration for the purpose of default arguments. |
| FunctionDecl *PrevForDefaultArgs = Old; |
| for (/**/; PrevForDefaultArgs; |
| // Don't bother looking back past the latest decl if this is a local |
| // extern declaration; nothing else could work. |
| PrevForDefaultArgs = New->isLocalExternDecl() |
| ? nullptr |
| : PrevForDefaultArgs->getPreviousDecl()) { |
| // Ignore hidden declarations. |
| if (!LookupResult::isVisible(*this, PrevForDefaultArgs)) |
| continue; |
| |
| if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) && |
| !New->isCXXClassMember()) { |
| // Ignore default arguments of old decl if they are not in |
| // the same scope and this is not an out-of-line definition of |
| // a member function. |
| continue; |
| } |
| |
| if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) { |
| // If only one of these is a local function declaration, then they are |
| // declared in different scopes, even though isDeclInScope may think |
| // they're in the same scope. (If both are local, the scope check is |
| // sufficient, and if neither is local, then they are in the same scope.) |
| continue; |
| } |
| |
| // We found the right previous declaration. |
| break; |
| } |
| |
| // C++ [dcl.fct.default]p4: |
| // For non-template functions, default arguments can be added in |
| // later declarations of a function in the same |
| // scope. Declarations in different scopes have completely |
| // distinct sets of default arguments. That is, declarations in |
| // inner scopes do not acquire default arguments from |
| // declarations in outer scopes, and vice versa. In a given |
| // function declaration, all parameters subsequent to a |
| // parameter with a default argument shall have default |
| // arguments supplied in this or previous declarations. A |
| // default argument shall not be redefined by a later |
| // declaration (not even to the same value). |
| // |
| // C++ [dcl.fct.default]p6: |
| // Except for member functions of class templates, the default arguments |
| // in a member function definition that appears outside of the class |
| // definition are added to the set of default arguments provided by the |
| // member function declaration in the class definition. |
| for (unsigned p = 0, NumParams = PrevForDefaultArgs |
| ? PrevForDefaultArgs->getNumParams() |
| : 0; |
| p < NumParams; ++p) { |
| ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p); |
| ParmVarDecl *NewParam = New->getParamDecl(p); |
| |
| bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false; |
| bool NewParamHasDfl = NewParam->hasDefaultArg(); |
| |
| if (OldParamHasDfl && NewParamHasDfl) { |
| unsigned DiagDefaultParamID = |
| diag::err_param_default_argument_redefinition; |
| |
| // MSVC accepts that default parameters be redefined for member functions |
| // of template class. The new default parameter's value is ignored. |
| Invalid = true; |
| if (getLangOpts().MicrosoftExt) { |
| CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New); |
| if (MD && MD->getParent()->getDescribedClassTemplate()) { |
| // Merge the old default argument into the new parameter. |
| NewParam->setHasInheritedDefaultArg(); |
| if (OldParam->hasUninstantiatedDefaultArg()) |
| NewParam->setUninstantiatedDefaultArg( |
| OldParam->getUninstantiatedDefaultArg()); |
| else |
| NewParam->setDefaultArg(OldParam->getInit()); |
| DiagDefaultParamID = diag::ext_param_default_argument_redefinition; |
| Invalid = false; |
| } |
| } |
| |
| // FIXME: If we knew where the '=' was, we could easily provide a fix-it |
| // hint here. Alternatively, we could walk the type-source information |
| // for NewParam to find the last source location in the type... but it |
| // isn't worth the effort right now. This is the kind of test case that |
| // is hard to get right: |
| // int f(int); |
| // void g(int (*fp)(int) = f); |
| // void g(int (*fp)(int) = &f); |
| Diag(NewParam->getLocation(), DiagDefaultParamID) |
| << NewParam->getDefaultArgRange(); |
| |
| // Look for the function declaration where the default argument was |
| // actually written, which may be a declaration prior to Old. |
| for (auto Older = PrevForDefaultArgs; |
| OldParam->hasInheritedDefaultArg(); /**/) { |
| Older = Older->getPreviousDecl(); |
| OldParam = Older->getParamDecl(p); |
| } |
| |
| Diag(OldParam->getLocation(), diag::note_previous_definition) |
| << OldParam->getDefaultArgRange(); |
| } else if (OldParamHasDfl) { |
| // Merge the old default argument into the new parameter unless the new |
| // function is a friend declaration in a template class. In the latter |
| // case the default arguments will be inherited when the friend |
| // declaration will be instantiated. |
| if (New->getFriendObjectKind() == Decl::FOK_None || |
| !New->getLexicalDeclContext()->isDependentContext()) { |
| // It's important to use getInit() here; getDefaultArg() |
| // strips off any top-level ExprWithCleanups. |
| NewParam->setHasInheritedDefaultArg(); |
| if (OldParam->hasUnparsedDefaultArg()) |
| NewParam->setUnparsedDefaultArg(); |
| else if (OldParam->hasUninstantiatedDefaultArg()) |
| NewParam->setUninstantiatedDefaultArg( |
| OldParam->getUninstantiatedDefaultArg()); |
| else |
| NewParam->setDefaultArg(OldParam->getInit()); |
| } |
| } else if (NewParamHasDfl) { |
| if (New->getDescribedFunctionTemplate()) { |
| // Paragraph 4, quoted above, only applies to non-template functions. |
| Diag(NewParam->getLocation(), |
| diag::err_param_default_argument_template_redecl) |
| << NewParam->getDefaultArgRange(); |
| Diag(PrevForDefaultArgs->getLocation(), |
| diag::note_template_prev_declaration) |
| << false; |
| } else if (New->getTemplateSpecializationKind() |
| != TSK_ImplicitInstantiation && |
| New->getTemplateSpecializationKind() != TSK_Undeclared) { |
| // C++ [temp.expr.spec]p21: |
| // Default function arguments shall not be specified in a declaration |
| // or a definition for one of the following explicit specializations: |
| // - the explicit specialization of a function template; |
| // - the explicit specialization of a member function template; |
| // - the explicit specialization of a member function of a class |
| // template where the class template specialization to which the |
| // member function specialization belongs is implicitly |
| // instantiated. |
| Diag(NewParam->getLocation(), diag::err_template_spec_default_arg) |
| << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization) |
| << New->getDeclName() |
| << NewParam->getDefaultArgRange(); |
| } else if (New->getDeclContext()->isDependentContext()) { |
| // C++ [dcl.fct.default]p6 (DR217): |
| // Default arguments for a member function of a class template shall |
| // be specified on the initial declaration of the member function |
| // within the class template. |
| // |
| // Reading the tea leaves a bit in DR217 and its reference to DR205 |
| // leads me to the conclusion that one cannot add default function |
| // arguments for an out-of-line definition of a member function of a |
| // dependent type. |
| int WhichKind = 2; |
| if (CXXRecordDecl *Record |
| = dyn_cast<CXXRecordDecl>(New->getDeclContext())) { |
| if (Record->getDescribedClassTemplate()) |
| WhichKind = 0; |
| else if (isa<ClassTemplatePartialSpecializationDecl>(Record)) |
| WhichKind = 1; |
| else |
| WhichKind = 2; |
| } |
| |
| Diag(NewParam->getLocation(), |
| diag::err_param_default_argument_member_template_redecl) |
| << WhichKind |
| << NewParam->getDefaultArgRange(); |
| } |
| } |
| } |
| |
| // DR1344: If a default argument is added outside a class definition and that |
| // default argument makes the function a special member function, the program |
| // is ill-formed. This can only happen for constructors. |
| if (isa<CXXConstructorDecl>(New) && |
| New->getMinRequiredArguments() < Old->getMinRequiredArguments()) { |
| CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)), |
| OldSM = getSpecialMember(cast<CXXMethodDecl>(Old)); |
| if (NewSM != OldSM) { |
| ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments()); |
| assert(NewParam->hasDefaultArg()); |
| Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special) |
| << NewParam->getDefaultArgRange() << NewSM; |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| } |
| } |
| |
| const FunctionDecl *Def; |
| // C++11 [dcl.constexpr]p1: If any declaration of a function or function |
| // template has a constexpr specifier then all its declarations shall |
| // contain the constexpr specifier. |
| if (New->getConstexprKind() != Old->getConstexprKind()) { |
| Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) |
| << New << New->getConstexprKind() << Old->getConstexprKind(); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| Invalid = true; |
| } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && |
| Old->isDefined(Def) && |
| // If a friend function is inlined but does not have 'inline' |
| // specifier, it is a definition. Do not report attribute conflict |
| // in this case, redefinition will be diagnosed later. |
| (New->isInlineSpecified() || |
| New->getFriendObjectKind() == Decl::FOK_None)) { |
| // C++11 [dcl.fcn.spec]p4: |
| // If the definition of a function appears in a translation unit before its |
| // first declaration as inline, the program is ill-formed. |
| Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New; |
| Diag(Def->getLocation(), diag::note_previous_definition); |
| Invalid = true; |
| } |
| |
| // C++17 [temp.deduct.guide]p3: |
| // Two deduction guide declarations in the same translation unit |
| // for the same class template shall not have equivalent |
| // parameter-declaration-clauses. |
| if (isa<CXXDeductionGuideDecl>(New) && |
| !New->isFunctionTemplateSpecialization()) { |
| Diag(New->getLocation(), diag::err_deduction_guide_redeclared); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| } |
| |
| // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default |
| // argument expression, that declaration shall be a definition and shall be |
| // the only declaration of the function or function template in the |
| // translation unit. |
| if (Old->getFriendObjectKind() == Decl::FOK_Undeclared && |
| functionDeclHasDefaultArgument(Old)) { |
| Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| Invalid = true; |
| } |
| |
| return Invalid; |
| } |
| |
| NamedDecl * |
| Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, |
| MultiTemplateParamsArg TemplateParamLists) { |
| assert(D.isDecompositionDeclarator()); |
| const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator(); |
| |
| // The syntax only allows a decomposition declarator as a simple-declaration, |
| // a for-range-declaration, or a condition in Clang, but we parse it in more |
| // cases than that. |
| if (!D.mayHaveDecompositionDeclarator()) { |
| Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context) |
| << Decomp.getSourceRange(); |
| return nullptr; |
| } |
| |
| if (!TemplateParamLists.empty()) { |
| // FIXME: There's no rule against this, but there are also no rules that |
| // would actually make it usable, so we reject it for now. |
| Diag(TemplateParamLists.front()->getTemplateLoc(), |
| diag::err_decomp_decl_template); |
| return nullptr; |
| } |
| |
| Diag(Decomp.getLSquareLoc(), |
| !getLangOpts().CPlusPlus17 |
| ? diag::ext_decomp_decl |
| : D.getContext() == DeclaratorContext::ConditionContext |
| ? diag::ext_decomp_decl_cond |
| : diag::warn_cxx14_compat_decomp_decl) |
| << Decomp.getSourceRange(); |
| |
| // The semantic context is always just the current context. |
| DeclContext *const DC = CurContext; |
| |
| // C++17 [dcl.dcl]/8: |
| // The decl-specifier-seq shall contain only the type-specifier auto |
| // and cv-qualifiers. |
| // C++2a [dcl.dcl]/8: |
| // If decl-specifier-seq contains any decl-specifier other than static, |
| // thread_local, auto, or cv-qualifiers, the program is ill-formed. |
| auto &DS = D.getDeclSpec(); |
| { |
| SmallVector<StringRef, 8> BadSpecifiers; |
| SmallVector<SourceLocation, 8> BadSpecifierLocs; |
| SmallVector<StringRef, 8> CPlusPlus20Specifiers; |
| SmallVector<SourceLocation, 8> CPlusPlus20SpecifierLocs; |
| if (auto SCS = DS.getStorageClassSpec()) { |
| if (SCS == DeclSpec::SCS_static) { |
| CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(SCS)); |
| CPlusPlus20SpecifierLocs.push_back(DS.getStorageClassSpecLoc()); |
| } else { |
| BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS)); |
| BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc()); |
| } |
| } |
| if (auto TSCS = DS.getThreadStorageClassSpec()) { |
| CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(TSCS)); |
| CPlusPlus20SpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc()); |
| } |
| if (DS.hasConstexprSpecifier()) { |
| BadSpecifiers.push_back( |
| DeclSpec::getSpecifierName(DS.getConstexprSpecifier())); |
| BadSpecifierLocs.push_back(DS.getConstexprSpecLoc()); |
| } |
| if (DS.isInlineSpecified()) { |
| BadSpecifiers.push_back("inline"); |
| BadSpecifierLocs.push_back(DS.getInlineSpecLoc()); |
| } |
| if (!BadSpecifiers.empty()) { |
| auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec); |
| Err << (int)BadSpecifiers.size() |
| << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " "); |
| // Don't add FixItHints to remove the specifiers; we do still respect |
| // them when building the underlying variable. |
| for (auto Loc : BadSpecifierLocs) |
| Err << SourceRange(Loc, Loc); |
| } else if (!CPlusPlus20Specifiers.empty()) { |
| auto &&Warn = Diag(CPlusPlus20SpecifierLocs.front(), |
| getLangOpts().CPlusPlus2a |
| ? diag::warn_cxx17_compat_decomp_decl_spec |
| : diag::ext_decomp_decl_spec); |
| Warn << (int)CPlusPlus20Specifiers.size() |
| << llvm::join(CPlusPlus20Specifiers.begin(), |
| CPlusPlus20Specifiers.end(), " "); |
| for (auto Loc : CPlusPlus20SpecifierLocs) |
| Warn << SourceRange(Loc, Loc); |
| } |
| // We can't recover from it being declared as a typedef. |
| if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) |
| return nullptr; |
| } |
| |
| // C++2a [dcl.struct.bind]p1: |
| // A cv that includes volatile is deprecated |
| if ((DS.getTypeQualifiers() & DeclSpec::TQ_volatile) && |
| getLangOpts().CPlusPlus2a) |
| Diag(DS.getVolatileSpecLoc(), |
| diag::warn_deprecated_volatile_structured_binding); |
| |
| TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); |
| QualType R = TInfo->getType(); |
| |
| if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, |
| UPPC_DeclarationType)) |
| D.setInvalidType(); |
| |
| // The syntax only allows a single ref-qualifier prior to the decomposition |
| // declarator. No other declarator chunks are permitted. Also check the type |
| // specifier here. |
| if (DS.getTypeSpecType() != DeclSpec::TST_auto || |
| D.hasGroupingParens() || D.getNumTypeObjects() > 1 || |
| (D.getNumTypeObjects() == 1 && |
| D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) { |
| Diag(Decomp.getLSquareLoc(), |
| (D.hasGroupingParens() || |
| (D.getNumTypeObjects() && |
| D.getTypeObject(0).Kind == DeclaratorChunk::Paren)) |
| ? diag::err_decomp_decl_parens |
| : diag::err_decomp_decl_type) |
| << R; |
| |
| // In most cases, there's no actual problem with an explicitly-specified |
| // type, but a function type won't work here, and ActOnVariableDeclarator |
| // shouldn't be called for such a type. |
| if (R->isFunctionType()) |
| D.setInvalidType(); |
| } |
| |
| // Build the BindingDecls. |
| SmallVector<BindingDecl*, 8> Bindings; |
| |
| // Build the BindingDecls. |
| for (auto &B : D.getDecompositionDeclarator().bindings()) { |
| // Check for name conflicts. |
| DeclarationNameInfo NameInfo(B.Name, B.NameLoc); |
| LookupResult Previous(*this, NameInfo, LookupOrdinaryName, |
| ForVisibleRedeclaration); |
| LookupName(Previous, S, |
| /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit()); |
| |
| // It's not permitted to shadow a template parameter name. |
| if (Previous.isSingleResult() && |
| Previous.getFoundDecl()->isTemplateParameter()) { |
| DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), |
| Previous.getFoundDecl()); |
| Previous.clear(); |
| } |
| |
| bool ConsiderLinkage = DC->isFunctionOrMethod() && |
| DS.getStorageClassSpec() == DeclSpec::SCS_extern; |
| FilterLookupForScope(Previous, DC, S, ConsiderLinkage, |
| /*AllowInlineNamespace*/false); |
| if (!Previous.empty()) { |
| auto *Old = Previous.getRepresentativeDecl(); |
| Diag(B.NameLoc, diag::err_redefinition) << B.Name; |
| Diag(Old->getLocation(), diag::note_previous_definition); |
| } |
| |
| auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name); |
| PushOnScopeChains(BD, S, true); |
| Bindings.push_back(BD); |
| ParsingInitForAutoVars.insert(BD); |
| } |
| |
| // There are no prior lookup results for the variable itself, because it |
| // is unnamed. |
| DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr, |
| Decomp.getLSquareLoc()); |
| LookupResult Previous(*this, NameInfo, LookupOrdinaryName, |
| ForVisibleRedeclaration); |
| |
| // Build the variable that holds the non-decomposed object. |
| bool AddToScope = true; |
| NamedDecl *New = |
| ActOnVariableDeclarator(S, D, DC, TInfo, Previous, |
| MultiTemplateParamsArg(), AddToScope, Bindings); |
| if (AddToScope) { |
| S->AddDecl(New); |
| CurContext->addHiddenDecl(New); |
| } |
| |
| if (isInOpenMPDeclareTargetContext()) |
| checkDeclIsAllowedInOpenMPTarget(nullptr, New); |
| |
| return New; |
| } |
| |
| static bool checkSimpleDecomposition( |
| Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src, |
| QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType, |
| llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) { |
| if ((int64_t)Bindings.size() != NumElems) { |
| S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) |
| << DecompType << (unsigned)Bindings.size() << NumElems.toString(10) |
| << (NumElems < Bindings.size()); |
| return true; |
| } |
| |
| unsigned I = 0; |
| for (auto *B : Bindings) { |
| SourceLocation Loc = B->getLocation(); |
| ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); |
| if (E.isInvalid()) |
| return true; |
| E = GetInit(Loc, E.get(), I++); |
| if (E.isInvalid()) |
| return true; |
| B->setBinding(ElemType, E.get()); |
| } |
| |
| return false; |
| } |
| |
| static bool checkArrayLikeDecomposition(Sema &S, |
| ArrayRef<BindingDecl *> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const llvm::APSInt &NumElems, |
| QualType ElemType) { |
| return checkSimpleDecomposition( |
| S, Bindings, Src, DecompType, NumElems, ElemType, |
| [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { |
| ExprResult E = S.ActOnIntegerConstant(Loc, I); |
| if (E.isInvalid()) |
| return ExprError(); |
| return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc); |
| }); |
| } |
| |
| static bool checkArrayDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const ConstantArrayType *CAT) { |
| return checkArrayLikeDecomposition(S, Bindings, Src, DecompType, |
| llvm::APSInt(CAT->getSize()), |
| CAT->getElementType()); |
| } |
| |
| static bool checkVectorDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const VectorType *VT) { |
| return checkArrayLikeDecomposition( |
| S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()), |
| S.Context.getQualifiedType(VT->getElementType(), |
| DecompType.getQualifiers())); |
| } |
| |
| static bool checkComplexDecomposition(Sema &S, |
| ArrayRef<BindingDecl *> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const ComplexType *CT) { |
| return checkSimpleDecomposition( |
| S, Bindings, Src, DecompType, llvm::APSInt::get(2), |
| S.Context.getQualifiedType(CT->getElementType(), |
| DecompType.getQualifiers()), |
| [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult { |
| return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base); |
| }); |
| } |
| |
| static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy, |
| TemplateArgumentListInfo &Args) { |
| SmallString<128> SS; |
| llvm::raw_svector_ostream OS(SS); |
| bool First = true; |
| for (auto &Arg : Args.arguments()) { |
| if (!First) |
| OS << ", "; |
| Arg.getArgument().print(PrintingPolicy, OS); |
| First = false; |
| } |
| return OS.str(); |
| } |
| |
| static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup, |
| SourceLocation Loc, StringRef Trait, |
| TemplateArgumentListInfo &Args, |
| unsigned DiagID) { |
| auto DiagnoseMissing = [&] { |
| if (DiagID) |
| S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(), |
| Args); |
| return true; |
| }; |
| |
| // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine. |
| NamespaceDecl *Std = S.getStdNamespace(); |
| if (!Std) |
| return DiagnoseMissing(); |
| |
| // Look up the trait itself, within namespace std. We can diagnose various |
| // problems with this lookup even if we've been asked to not diagnose a |
| // missing specialization, because this can only fail if the user has been |
| // declaring their own names in namespace std or we don't support the |
| // standard library implementation in use. |
| LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait), |
| Loc, Sema::LookupOrdinaryName); |
| if (!S.LookupQualifiedName(Result, Std)) |
| return DiagnoseMissing(); |
| if (Result.isAmbiguous()) |
| return true; |
| |
| ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>(); |
| if (!TraitTD) { |
| Result.suppressDiagnostics(); |
| NamedDecl *Found = *Result.begin(); |
| S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait; |
| S.Diag(Found->getLocation(), diag::note_declared_at); |
| return true; |
| } |
| |
| // Build the template-id. |
| QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args); |
| if (TraitTy.isNull()) |
| return true; |
| if (!S.isCompleteType(Loc, TraitTy)) { |
| if (DiagID) |
| S.RequireCompleteType( |
| Loc, TraitTy, DiagID, |
| printTemplateArgs(S.Context.getPrintingPolicy(), Args)); |
| return true; |
| } |
| |
| CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl(); |
| assert(RD && "specialization of class template is not a class?"); |
| |
| // Look up the member of the trait type. |
| S.LookupQualifiedName(TraitMemberLookup, RD); |
| return TraitMemberLookup.isAmbiguous(); |
| } |
| |
| static TemplateArgumentLoc |
| getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T, |
| uint64_t I) { |
| TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T); |
| return S.getTrivialTemplateArgumentLoc(Arg, T, Loc); |
| } |
| |
| static TemplateArgumentLoc |
| getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) { |
| return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc); |
| } |
| |
| namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; } |
| |
| static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, |
| llvm::APSInt &Size) { |
| EnterExpressionEvaluationContext ContextRAII( |
| S, Sema::ExpressionEvaluationContext::ConstantEvaluated); |
| |
| DeclarationName Value = S.PP.getIdentifierInfo("value"); |
| LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName); |
| |
| // Form template argument list for tuple_size<T>. |
| TemplateArgumentListInfo Args(Loc, Loc); |
| Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); |
| |
| // If there's no tuple_size specialization or the lookup of 'value' is empty, |
| // it's not tuple-like. |
| if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/ 0) || |
| R.empty()) |
| return IsTupleLike::NotTupleLike; |
| |
| // If we get this far, we've committed to the tuple interpretation, but |
| // we can still fail if there actually isn't a usable ::value. |
| |
| struct ICEDiagnoser : Sema::VerifyICEDiagnoser { |
| LookupResult &R; |
| TemplateArgumentListInfo &Args; |
| ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args) |
| : R(R), Args(Args) {} |
| void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) { |
| S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant) |
| << printTemplateArgs(S.Context.getPrintingPolicy(), Args); |
| } |
| } Diagnoser(R, Args); |
| |
| ExprResult E = |
| S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false); |
| if (E.isInvalid()) |
| return IsTupleLike::Error; |
| |
| E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false); |
| if (E.isInvalid()) |
| return IsTupleLike::Error; |
| |
| return IsTupleLike::TupleLike; |
| } |
| |
| /// \return std::tuple_element<I, T>::type. |
| static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc, |
| unsigned I, QualType T) { |
| // Form template argument list for tuple_element<I, T>. |
| TemplateArgumentListInfo Args(Loc, Loc); |
| Args.addArgument( |
| getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); |
| Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); |
| |
| DeclarationName TypeDN = S.PP.getIdentifierInfo("type"); |
| LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName); |
| if (lookupStdTypeTraitMember( |
| S, R, Loc, "tuple_element", Args, |
| diag::err_decomp_decl_std_tuple_element_not_specialized)) |
| return QualType(); |
| |
| auto *TD = R.getAsSingle<TypeDecl>(); |
| if (!TD) { |
| R.suppressDiagnostics(); |
| S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized) |
| << printTemplateArgs(S.Context.getPrintingPolicy(), Args); |
| if (!R.empty()) |
| S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at); |
| return QualType(); |
| } |
| |
| return S.Context.getTypeDeclType(TD); |
| } |
| |
| namespace { |
| struct BindingDiagnosticTrap { |
| Sema &S; |
| DiagnosticErrorTrap Trap; |
| BindingDecl *BD; |
| |
| BindingDiagnosticTrap(Sema &S, BindingDecl *BD) |
| : S(S), Trap(S.Diags), BD(BD) {} |
| ~BindingDiagnosticTrap() { |
| if (Trap.hasErrorOccurred()) |
| S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD; |
| } |
| }; |
| } |
| |
| static bool checkTupleLikeDecomposition(Sema &S, |
| ArrayRef<BindingDecl *> Bindings, |
| VarDecl *Src, QualType DecompType, |
| const llvm::APSInt &TupleSize) { |
| if ((int64_t)Bindings.size() != TupleSize) { |
| S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) |
| << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10) |
| << (TupleSize < Bindings.size()); |
| return true; |
| } |
| |
| if (Bindings.empty()) |
| return false; |
| |
| DeclarationName GetDN = S.PP.getIdentifierInfo("get"); |
| |
| // [dcl.decomp]p3: |
| // The unqualified-id get is looked up in the scope of E by class member |
| // access lookup ... |
| LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName); |
| bool UseMemberGet = false; |
| if (S.isCompleteType(Src->getLocation(), DecompType)) { |
| if (auto *RD = DecompType->getAsCXXRecordDecl()) |
| S.LookupQualifiedName(MemberGet, RD); |
| if (MemberGet.isAmbiguous()) |
| return true; |
| // ... and if that finds at least one declaration that is a function |
| // template whose first template parameter is a non-type parameter ... |
| for (NamedDecl *D : MemberGet) { |
| if (FunctionTemplateDecl *FTD = |
| dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) { |
| TemplateParameterList *TPL = FTD->getTemplateParameters(); |
| if (TPL->size() != 0 && |
| isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) { |
| // ... the initializer is e.get<i>(). |
| UseMemberGet = true; |
| break; |
| } |
| } |
| } |
| } |
| |
| unsigned I = 0; |
| for (auto *B : Bindings) { |
| BindingDiagnosticTrap Trap(S, B); |
| SourceLocation Loc = B->getLocation(); |
| |
| ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); |
| if (E.isInvalid()) |
| return true; |
| |
| // e is an lvalue if the type of the entity is an lvalue reference and |
| // an xvalue otherwise |
| if (!Src->getType()->isLValueReferenceType()) |
| E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp, |
| E.get(), nullptr, VK_XValue); |
| |
| TemplateArgumentListInfo Args(Loc, Loc); |
| Args.addArgument( |
| getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I)); |
| |
| if (UseMemberGet) { |
| // if [lookup of member get] finds at least one declaration, the |
| // initializer is e.get<i-1>(). |
| E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false, |
| CXXScopeSpec(), SourceLocation(), nullptr, |
| MemberGet, &Args, nullptr); |
| if (E.isInvalid()) |
| return true; |
| |
| E = S.BuildCallExpr(nullptr, E.get(), Loc, None, Loc); |
| } else { |
| // Otherwise, the initializer is get<i-1>(e), where get is looked up |
| // in the associated namespaces. |
| Expr *Get = UnresolvedLookupExpr::Create( |
| S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), |
| DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args, |
| UnresolvedSetIterator(), UnresolvedSetIterator()); |
| |
| Expr *Arg = E.get(); |
| E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc); |
| } |
| if (E.isInvalid()) |
| return true; |
| Expr *Init = E.get(); |
| |
| // Given the type T designated by std::tuple_element<i - 1, E>::type, |
| QualType T = getTupleLikeElementType(S, Loc, I, DecompType); |
| if (T.isNull()) |
| return true; |
| |
| // each vi is a variable of type "reference to T" initialized with the |
| // initializer, where the reference is an lvalue reference if the |
| // initializer is an lvalue and an rvalue reference otherwise |
| QualType RefType = |
| S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName()); |
| if (RefType.isNull()) |
| return true; |
| auto *RefVD = VarDecl::Create( |
| S.Context, Src->getDeclContext(), Loc, Loc, |
| B->getDeclName().getAsIdentifierInfo(), RefType, |
| S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass()); |
| RefVD->setLexicalDeclContext(Src->getLexicalDeclContext()); |
| RefVD->setTSCSpec(Src->getTSCSpec()); |
| RefVD->setImplicit(); |
| if (Src->isInlineSpecified()) |
| RefVD->setInlineSpecified(); |
| RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD); |
| |
| InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD); |
| InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc); |
| InitializationSequence Seq(S, Entity, Kind, Init); |
| E = Seq.Perform(S, Entity, Kind, Init); |
| if (E.isInvalid()) |
| return true; |
| E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); |
| if (E.isInvalid()) |
| return true; |
| RefVD->setInit(E.get()); |
| if (!E.get()->isValueDependent()) |
| RefVD->checkInitIsICE(); |
| |
| E = S.BuildDeclarationNameExpr(CXXScopeSpec(), |
| DeclarationNameInfo(B->getDeclName(), Loc), |
| RefVD); |
| if (E.isInvalid()) |
| return true; |
| |
| B->setBinding(T, E.get()); |
| I++; |
| } |
| |
| return false; |
| } |
| |
| /// Find the base class to decompose in a built-in decomposition of a class type. |
| /// This base class search is, unfortunately, not quite like any other that we |
| /// perform anywhere else in C++. |
| static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc, |
| const CXXRecordDecl *RD, |
| CXXCastPath &BasePath) { |
| auto BaseHasFields = [](const CXXBaseSpecifier *Specifier, |
| CXXBasePath &Path) { |
| return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields(); |
| }; |
| |
| const CXXRecordDecl *ClassWithFields = nullptr; |
| AccessSpecifier AS = AS_public; |
| if (RD->hasDirectFields()) |
| // [dcl.decomp]p4: |
| // Otherwise, all of E's non-static data members shall be public direct |
| // members of E ... |
| ClassWithFields = RD; |
| else { |
| // ... or of ... |
| CXXBasePaths Paths; |
| Paths.setOrigin(const_cast<CXXRecordDecl*>(RD)); |
| if (!RD->lookupInBases(BaseHasFields, Paths)) { |
| // If no classes have fields, just decompose RD itself. (This will work |
| // if and only if zero bindings were provided.) |
| return DeclAccessPair::make(const_cast<CXXRecordDecl*>(RD), AS_public); |
| } |
| |
| CXXBasePath *BestPath = nullptr; |
| for (auto &P : Paths) { |
| if (!BestPath) |
| BestPath = &P; |
| else if (!S.Context.hasSameType(P.back().Base->getType(), |
| BestPath->back().Base->getType())) { |
| // ... the same ... |
| S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) |
| << false << RD << BestPath->back().Base->getType() |
| << P.back().Base->getType(); |
| return DeclAccessPair(); |
| } else if (P.Access < BestPath->Access) { |
| BestPath = &P; |
| } |
| } |
| |
| // ... unambiguous ... |
| QualType BaseType = BestPath->back().Base->getType(); |
| if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) { |
| S.Diag(Loc, diag::err_decomp_decl_ambiguous_base) |
| << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths); |
| return DeclAccessPair(); |
| } |
| |
| // ... [accessible, implied by other rules] base class of E. |
| S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD), |
| *BestPath, diag::err_decomp_decl_inaccessible_base); |
| AS = BestPath->Access; |
| |
| ClassWithFields = BaseType->getAsCXXRecordDecl(); |
| S.BuildBasePathArray(Paths, BasePath); |
| } |
| |
| // The above search did not check whether the selected class itself has base |
| // classes with fields, so check that now. |
| CXXBasePaths Paths; |
| if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) { |
| S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members) |
| << (ClassWithFields == RD) << RD << ClassWithFields |
| << Paths.front().back().Base->getType(); |
| return DeclAccessPair(); |
| } |
| |
| return DeclAccessPair::make(const_cast<CXXRecordDecl*>(ClassWithFields), AS); |
| } |
| |
| static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const CXXRecordDecl *OrigRD) { |
| if (S.RequireCompleteType(Src->getLocation(), DecompType, |
| diag::err_incomplete_type)) |
| return true; |
| |
| CXXCastPath BasePath; |
| DeclAccessPair BasePair = |
| findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath); |
| const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl()); |
| if (!RD) |
| return true; |
| QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD), |
| DecompType.getQualifiers()); |
| |
| auto DiagnoseBadNumberOfBindings = [&]() -> bool { |
| unsigned NumFields = |
| std::count_if(RD->field_begin(), RD->field_end(), |
| [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); }); |
| assert(Bindings.size() != NumFields); |
| S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings) |
| << DecompType << (unsigned)Bindings.size() << NumFields |
| << (NumFields < Bindings.size()); |
| return true; |
| }; |
| |
| // all of E's non-static data members shall be [...] well-formed |
| // when named as e.name in the context of the structured binding, |
| // E shall not have an anonymous union member, ... |
| unsigned I = 0; |
| for (auto *FD : RD->fields()) { |
| if (FD->isUnnamedBitfield()) |
| continue; |
| |
| if (FD->isAnonymousStructOrUnion()) { |
| S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member) |
| << DecompType << FD->getType()->isUnionType(); |
| S.Diag(FD->getLocation(), diag::note_declared_at); |
| return true; |
| } |
| |
| // We have a real field to bind. |
| if (I >= Bindings.size()) |
| return DiagnoseBadNumberOfBindings(); |
| auto *B = Bindings[I++]; |
| SourceLocation Loc = B->getLocation(); |
| |
| // The field must be accessible in the context of the structured binding. |
| // We already checked that the base class is accessible. |
| // FIXME: Add 'const' to AccessedEntity's classes so we can remove the |
| // const_cast here. |
| S.CheckStructuredBindingMemberAccess( |
| Loc, const_cast<CXXRecordDecl *>(OrigRD), |
| DeclAccessPair::make(FD, CXXRecordDecl::MergeAccess( |
| BasePair.getAccess(), FD->getAccess()))); |
| |
| // Initialize the binding to Src.FD. |
| ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc); |
| if (E.isInvalid()) |
| return true; |
| E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase, |
| VK_LValue, &BasePath); |
| if (E.isInvalid()) |
| return true; |
| E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc, |
| CXXScopeSpec(), FD, |
| DeclAccessPair::make(FD, FD->getAccess()), |
| DeclarationNameInfo(FD->getDeclName(), Loc)); |
| if (E.isInvalid()) |
| return true; |
| |
| // If the type of the member is T, the referenced type is cv T, where cv is |
| // the cv-qualification of the decomposition expression. |
| // |
| // FIXME: We resolve a defect here: if the field is mutable, we do not add |
| // 'const' to the type of the field. |
| Qualifiers Q = DecompType.getQualifiers(); |
| if (FD->isMutable()) |
| Q.removeConst(); |
| B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get()); |
| } |
| |
| if (I != Bindings.size()) |
| return DiagnoseBadNumberOfBindings(); |
| |
| return false; |
| } |
| |
| void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) { |
| QualType DecompType = DD->getType(); |
| |
| // If the type of the decomposition is dependent, then so is the type of |
| // each binding. |
| if (DecompType->isDependentType()) { |
| for (auto *B : DD->bindings()) |
| B->setType(Context.DependentTy); |
| return; |
| } |
| |
| DecompType = DecompType.getNonReferenceType(); |
| ArrayRef<BindingDecl*> Bindings = DD->bindings(); |
| |
| // C++1z [dcl.decomp]/2: |
| // If E is an array type [...] |
| // As an extension, we also support decomposition of built-in complex and |
| // vector types. |
| if (auto *CAT = Context.getAsConstantArrayType(DecompType)) { |
| if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT)) |
| DD->setInvalidDecl(); |
| return; |
| } |
| if (auto *VT = DecompType->getAs<VectorType>()) { |
| if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT)) |
| DD->setInvalidDecl(); |
| return; |
| } |
| if (auto *CT = DecompType->getAs<ComplexType>()) { |
| if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT)) |
| DD->setInvalidDecl(); |
| return; |
| } |
| |
| // C++1z [dcl.decomp]/3: |
| // if the expression std::tuple_size<E>::value is a well-formed integral |
| // constant expression, [...] |
| llvm::APSInt TupleSize(32); |
| switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) { |
| case IsTupleLike::Error: |
| DD->setInvalidDecl(); |
| return; |
| |
| case IsTupleLike::TupleLike: |
| if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize)) |
| DD->setInvalidDecl(); |
| return; |
| |
| case IsTupleLike::NotTupleLike: |
| break; |
| } |
| |
| // C++1z [dcl.dcl]/8: |
| // [E shall be of array or non-union class type] |
| CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl(); |
| if (!RD || RD->isUnion()) { |
| Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type) |
| << DD << !RD << DecompType; |
| DD->setInvalidDecl(); |
| return; |
| } |
| |
| // C++1z [dcl.decomp]/4: |
| // all of E's non-static data members shall be [...] direct members of |
| // E or of the same unambiguous public base class of E, ... |
| if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD)) |
| DD->setInvalidDecl(); |
| } |
| |
| /// Merge the exception specifications of two variable declarations. |
| /// |
| /// This is called when there's a redeclaration of a VarDecl. The function |
| /// checks if the redeclaration might have an exception specification and |
| /// validates compatibility and merges the specs if necessary. |
| void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) { |
| // Shortcut if exceptions are disabled. |
| if (!getLangOpts().CXXExceptions) |
| return; |
| |
| assert(Context.hasSameType(New->getType(), Old->getType()) && |
| "Should only be called if types are otherwise the same."); |
| |
| QualType NewType = New->getType(); |
| QualType OldType = Old->getType(); |
| |
| // We're only interested in pointers and references to functions, as well |
| // as pointers to member functions. |
| if (const ReferenceType *R = NewType->getAs<ReferenceType>()) { |
| NewType = R->getPointeeType(); |
| OldType = OldType->getAs<ReferenceType>()->getPointeeType(); |
| } else if (const PointerType *P = NewType->getAs<PointerType>()) { |
| NewType = P->getPointeeType(); |
| OldType = OldType->getAs<PointerType>()->getPointeeType(); |
| } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) { |
| NewType = M->getPointeeType(); |
| OldType = OldType->getAs<MemberPointerType>()->getPointeeType(); |
| } |
| |
| if (!NewType->isFunctionProtoType()) |
| return; |
| |
| // There's lots of special cases for functions. For function pointers, system |
| // libraries are hopefully not as broken so that we don't need these |
| // workarounds. |
| if (CheckEquivalentExceptionSpec( |
| OldType->getAs<FunctionProtoType>(), Old->getLocation(), |
| NewType->getAs<FunctionProtoType>(), New->getLocation())) { |
| New->setInvalidDecl(); |
| } |
| } |
| |
| /// CheckCXXDefaultArguments - Verify that the default arguments for a |
| /// function declaration are well-formed according to C++ |
| /// [dcl.fct.default]. |
| void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) { |
| unsigned NumParams = FD->getNumParams(); |
| unsigned p; |
| |
| // Find first parameter with a default argument |
| for (p = 0; p < NumParams; ++p) { |
| ParmVarDecl *Param = FD->getParamDecl(p); |
| if (Param->hasDefaultArg()) |
| break; |
| } |
| |
| // C++11 [dcl.fct.default]p4: |
| // In a given function declaration, each parameter subsequent to a parameter |
| // with a default argument shall have a default argument supplied in this or |
| // a previous declaration or shall be a function parameter pack. A default |
| // argument shall not be redefined by a later declaration (not even to the |
| // same value). |
| unsigned LastMissingDefaultArg = 0; |
| for (; p < NumParams; ++p) { |
| ParmVarDecl *Param = FD->getParamDecl(p); |
| if (!Param->hasDefaultArg() && !Param->isParameterPack()) { |
| if (Param->isInvalidDecl()) |
| /* We already complained about this parameter. */; |
| else if (Param->getIdentifier()) |
| Diag(Param->getLocation(), |
| diag::err_param_default_argument_missing_name) |
| << Param->getIdentifier(); |
| else |
| Diag(Param->getLocation(), |
| diag::err_param_default_argument_missing); |
| |
| LastMissingDefaultArg = p; |
| } |
| } |
| |
| if (LastMissingDefaultArg > 0) { |
| // Some default arguments were missing. Clear out all of the |
| // default arguments up to (and including) the last missing |
| // default argument, so that we leave the function parameters |
| // in a semantically valid state. |
| for (p = 0; p <= LastMissingDefaultArg; ++p) { |
| ParmVarDecl *Param = FD->getParamDecl(p); |
| if (Param->hasDefaultArg()) { |
| Param->setDefaultArg(nullptr); |
| } |
| } |
| } |
| } |
| |
| /// Check that the given type is a literal type. Issue a diagnostic if not, |
| /// if Kind is Diagnose. |
| /// \return \c true if a problem has been found (and optionally diagnosed). |
| template <typename... Ts> |
| static bool CheckLiteralType(Sema &SemaRef, Sema::CheckConstexprKind Kind, |
| SourceLocation Loc, QualType T, unsigned DiagID, |
| Ts &&...DiagArgs) { |
| if (T->isDependentType()) |
| return false; |
| |
| switch (Kind) { |
| case Sema::CheckConstexprKind::Diagnose: |
| return SemaRef.RequireLiteralType(Loc, T, DiagID, |
| std::forward<Ts>(DiagArgs)...); |
| |
| case Sema::CheckConstexprKind::CheckValid: |
| return !T->isLiteralType(SemaRef.Context); |
| } |
| |
| llvm_unreachable("unknown CheckConstexprKind"); |
| } |
| |
| /// Determine whether a destructor cannot be constexpr due to |
| static bool CheckConstexprDestructorSubobjects(Sema &SemaRef, |
| const CXXDestructorDecl *DD, |
| Sema::CheckConstexprKind Kind) { |
| auto Check = [&](SourceLocation Loc, QualType T, const FieldDecl *FD) { |
| const CXXRecordDecl *RD = |
| T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); |
| if (!RD || RD->hasConstexprDestructor()) |
| return true; |
| |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(DD->getLocation(), diag::err_constexpr_dtor_subobject) |
| << DD->getConstexprKind() << !FD |
| << (FD ? FD->getDeclName() : DeclarationName()) << T; |
| SemaRef.Diag(Loc, diag::note_constexpr_dtor_subobject) |
| << !FD << (FD ? FD->getDeclName() : DeclarationName()) << T; |
| } |
| return false; |
| }; |
| |
| const CXXRecordDecl *RD = DD->getParent(); |
| for (const CXXBaseSpecifier &B : RD->bases()) |
| if (!Check(B.getBaseTypeLoc(), B.getType(), nullptr)) |
| return false; |
| for (const FieldDecl *FD : RD->fields()) |
| if (!Check(FD->getLocation(), FD->getType(), FD)) |
| return false; |
| return true; |
| } |
| |
| // CheckConstexprParameterTypes - Check whether a function's parameter types |
| // are all literal types. If so, return true. If not, produce a suitable |
| // diagnostic and return false. |
| static bool CheckConstexprParameterTypes(Sema &SemaRef, |
| const FunctionDecl *FD, |
| Sema::CheckConstexprKind Kind) { |
| unsigned ArgIndex = 0; |
| const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>(); |
| for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(), |
| e = FT->param_type_end(); |
| i != e; ++i, ++ArgIndex) { |
| const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); |
| SourceLocation ParamLoc = PD->getLocation(); |
| if (CheckLiteralType(SemaRef, Kind, ParamLoc, *i, |
| diag::err_constexpr_non_literal_param, ArgIndex + 1, |
| PD->getSourceRange(), isa<CXXConstructorDecl>(FD), |
| FD->isConsteval())) |
| return false; |
| } |
| return true; |
| } |
| |
| /// Get diagnostic %select index for tag kind for |
| /// record diagnostic message. |
| /// WARNING: Indexes apply to particular diagnostics only! |
| /// |
| /// \returns diagnostic %select index. |
| static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) { |
| switch (Tag) { |
| case TTK_Struct: return 0; |
| case TTK_Interface: return 1; |
| case TTK_Class: return 2; |
| default: llvm_unreachable("Invalid tag kind for record diagnostic!"); |
| } |
| } |
| |
| static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, |
| Stmt *Body, |
| Sema::CheckConstexprKind Kind); |
| |
| // Check whether a function declaration satisfies the requirements of a |
| // constexpr function definition or a constexpr constructor definition. If so, |
| // return true. If not, produce appropriate diagnostics (unless asked not to by |
| // Kind) and return false. |
| // |
| // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. |
| bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD, |
| CheckConstexprKind Kind) { |
| const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); |
| if (MD && MD->isInstance()) { |
| // C++11 [dcl.constexpr]p4: |
| // The definition of a constexpr constructor shall satisfy the following |
| // constraints: |
| // - the class shall not have any virtual base classes; |
| // |
| // FIXME: This only applies to constructors and destructors, not arbitrary |
| // member functions. |
| const CXXRecordDecl *RD = MD->getParent(); |
| if (RD->getNumVBases()) { |
| if (Kind == CheckConstexprKind::CheckValid) |
| return false; |
| |
| Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) |
| << isa<CXXConstructorDecl>(NewFD) |
| << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); |
| for (const auto &I : RD->vbases()) |
| Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here) |
| << I.getSourceRange(); |
| return false; |
| } |
| } |
| |
| if (!isa<CXXConstructorDecl>(NewFD)) { |
| // C++11 [dcl.constexpr]p3: |
| // The definition of a constexpr function shall satisfy the following |
| // constraints: |
| // - it shall not be virtual; (removed in C++20) |
| const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); |
| if (Method && Method->isVirtual()) { |
| if (getLangOpts().CPlusPlus2a) { |
| if (Kind == CheckConstexprKind::Diagnose) |
| Diag(Method->getLocation(), diag::warn_cxx17_compat_constexpr_virtual); |
| } else { |
| if (Kind == CheckConstexprKind::CheckValid) |
| return false; |
| |
| Method = Method->getCanonicalDecl(); |
| Diag(Method->getLocation(), diag::err_constexpr_virtual); |
| |
| // If it's not obvious why this function is virtual, find an overridden |
| // function which uses the 'virtual' keyword. |
| const CXXMethodDecl *WrittenVirtual = Method; |
| while (!WrittenVirtual->isVirtualAsWritten()) |
| WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); |
| if (WrittenVirtual != Method) |
| Diag(WrittenVirtual->getLocation(), |
| diag::note_overridden_virtual_function); |
| return false; |
| } |
| } |
| |
| // - its return type shall be a literal type; |
| QualType RT = NewFD->getReturnType(); |
| if (CheckLiteralType(*this, Kind, NewFD->getLocation(), RT, |
| diag::err_constexpr_non_literal_return, |
| NewFD->isConsteval())) |
| return false; |
| } |
| |
| if (auto *Dtor = dyn_cast<CXXDestructorDecl>(NewFD)) { |
| // A destructor can be constexpr only if the defaulted destructor could be; |
| // we don't need to check the members and bases if we already know they all |
| // have constexpr destructors. |
| if (!Dtor->getParent()->defaultedDestructorIsConstexpr()) { |
| if (Kind == CheckConstexprKind::CheckValid) |
| return false; |
| if (!CheckConstexprDestructorSubobjects(*this, Dtor, Kind)) |
| return false; |
| } |
| } |
| |
| // - each of its parameter types shall be a literal type; |
| if (!CheckConstexprParameterTypes(*this, NewFD, Kind)) |
| return false; |
| |
| Stmt *Body = NewFD->getBody(); |
| assert(Body && |
| "CheckConstexprFunctionDefinition called on function with no body"); |
| return CheckConstexprFunctionBody(*this, NewFD, Body, Kind); |
| } |
| |
| /// Check the given declaration statement is legal within a constexpr function |
| /// body. C++11 [dcl.constexpr]p3,p4, and C++1y [dcl.constexpr]p3. |
| /// |
| /// \return true if the body is OK (maybe only as an extension), false if we |
| /// have diagnosed a problem. |
| static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, |
| DeclStmt *DS, SourceLocation &Cxx1yLoc, |
| Sema::CheckConstexprKind Kind) { |
| // C++11 [dcl.constexpr]p3 and p4: |
| // The definition of a constexpr function(p3) or constructor(p4) [...] shall |
| // contain only |
| for (const auto *DclIt : DS->decls()) { |
| switch (DclIt->getKind()) { |
| case Decl::StaticAssert: |
| case Decl::Using: |
| case Decl::UsingShadow: |
| case Decl::UsingDirective: |
| case Decl::UnresolvedUsingTypename: |
| case Decl::UnresolvedUsingValue: |
| // - static_assert-declarations |
| // - using-declarations, |
| // - using-directives, |
| continue; |
| |
| case Decl::Typedef: |
| case Decl::TypeAlias: { |
| // - typedef declarations and alias-declarations that do not define |
| // classes or enumerations, |
| const auto *TN = cast<TypedefNameDecl>(DclIt); |
| if (TN->getUnderlyingType()->isVariablyModifiedType()) { |
| // Don't allow variably-modified types in constexpr functions. |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc(); |
| SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla) |
| << TL.getSourceRange() << TL.getType() |
| << isa<CXXConstructorDecl>(Dcl); |
| } |
| return false; |
| } |
| continue; |
| } |
| |
| case Decl::Enum: |
| case Decl::CXXRecord: |
| // C++1y allows types to be defined, not just declared. |
| if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition()) { |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(DS->getBeginLoc(), |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_type_definition |
| : diag::ext_constexpr_type_definition) |
| << isa<CXXConstructorDecl>(Dcl); |
| } else if (!SemaRef.getLangOpts().CPlusPlus14) { |
| return false; |
| } |
| } |
| continue; |
| |
| case Decl::EnumConstant: |
| case Decl::IndirectField: |
| case Decl::ParmVar: |
| // These can only appear with other declarations which are banned in |
| // C++11 and permitted in C++1y, so ignore them. |
| continue; |
| |
| case Decl::Var: |
| case Decl::Decomposition: { |
| // C++1y [dcl.constexpr]p3 allows anything except: |
| // a definition of a variable of non-literal type or of static or |
| // thread storage duration or [before C++2a] for which no |
| // initialization is performed. |
| const auto *VD = cast<VarDecl>(DclIt); |
| if (VD->isThisDeclarationADefinition()) { |
| if (VD->isStaticLocal()) { |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(VD->getLocation(), |
| diag::err_constexpr_local_var_static) |
| << isa<CXXConstructorDecl>(Dcl) |
| << (VD->getTLSKind() == VarDecl::TLS_Dynamic); |
| } |
| return false; |
| } |
| if (CheckLiteralType(SemaRef, Kind, VD->getLocation(), VD->getType(), |
| diag::err_constexpr_local_var_non_literal_type, |
| isa<CXXConstructorDecl>(Dcl))) |
| return false; |
| if (!VD->getType()->isDependentType() && |
| !VD->hasInit() && !VD->isCXXForRangeDecl()) { |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag( |
| VD->getLocation(), |
| SemaRef.getLangOpts().CPlusPlus2a |
| ? diag::warn_cxx17_compat_constexpr_local_var_no_init |
| : diag::ext_constexpr_local_var_no_init) |
| << isa<CXXConstructorDecl>(Dcl); |
| } else if (!SemaRef.getLangOpts().CPlusPlus2a) { |
| return false; |
| } |
| continue; |
| } |
| } |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(VD->getLocation(), |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_local_var |
| : diag::ext_constexpr_local_var) |
| << isa<CXXConstructorDecl>(Dcl); |
| } else if (!SemaRef.getLangOpts().CPlusPlus14) { |
| return false; |
| } |
| continue; |
| } |
| |
| case Decl::NamespaceAlias: |
| case Decl::Function: |
| // These are disallowed in C++11 and permitted in C++1y. Allow them |
| // everywhere as an extension. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = DS->getBeginLoc(); |
| continue; |
| |
| default: |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) |
| << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval(); |
| } |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /// Check that the given field is initialized within a constexpr constructor. |
| /// |
| /// \param Dcl The constexpr constructor being checked. |
| /// \param Field The field being checked. This may be a member of an anonymous |
| /// struct or union nested within the class being checked. |
| /// \param Inits All declarations, including anonymous struct/union members and |
| /// indirect members, for which any initialization was provided. |
| /// \param Diagnosed Whether we've emitted the error message yet. Used to attach |
| /// multiple notes for different members to the same error. |
| /// \param Kind Whether we're diagnosing a constructor as written or determining |
| /// whether the formal requirements are satisfied. |
| /// \return \c false if we're checking for validity and the constructor does |
| /// not satisfy the requirements on a constexpr constructor. |
| static bool CheckConstexprCtorInitializer(Sema &SemaRef, |
| const FunctionDecl *Dcl, |
| FieldDecl *Field, |
| llvm::SmallSet<Decl*, 16> &Inits, |
| bool &Diagnosed, |
| Sema::CheckConstexprKind Kind) { |
| // In C++20 onwards, there's nothing to check for validity. |
| if (Kind == Sema::CheckConstexprKind::CheckValid && |
| SemaRef.getLangOpts().CPlusPlus2a) |
| return true; |
| |
| if (Field->isInvalidDecl()) |
| return true; |
| |
| if (Field->isUnnamedBitfield()) |
| return true; |
| |
| // Anonymous unions with no variant members and empty anonymous structs do not |
| // need to be explicitly initialized. FIXME: Anonymous structs that contain no |
| // indirect fields don't need initializing. |
| if (Field->isAnonymousStructOrUnion() && |
| (Field->getType()->isUnionType() |
| ? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers() |
| : Field->getType()->getAsCXXRecordDecl()->isEmpty())) |
| return true; |
| |
| if (!Inits.count(Field)) { |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| if (!Diagnosed) { |
| SemaRef.Diag(Dcl->getLocation(), |
| SemaRef.getLangOpts().CPlusPlus2a |
| ? diag::warn_cxx17_compat_constexpr_ctor_missing_init |
| : diag::ext_constexpr_ctor_missing_init); |
| Diagnosed = true; |
| } |
| SemaRef.Diag(Field->getLocation(), |
| diag::note_constexpr_ctor_missing_init); |
| } else if (!SemaRef.getLangOpts().CPlusPlus2a) { |
| return false; |
| } |
| } else if (Field->isAnonymousStructOrUnion()) { |
| const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl(); |
| for (auto *I : RD->fields()) |
| // If an anonymous union contains an anonymous struct of which any member |
| // is initialized, all members must be initialized. |
| if (!RD->isUnion() || Inits.count(I)) |
| if (!CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed, |
| Kind)) |
| return false; |
| } |
| return true; |
| } |
| |
| /// Check the provided statement is allowed in a constexpr function |
| /// definition. |
| static bool |
| CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, |
| SmallVectorImpl<SourceLocation> &ReturnStmts, |
| SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc, |
| Sema::CheckConstexprKind Kind) { |
| // - its function-body shall be [...] a compound-statement that contains only |
| switch (S->getStmtClass()) { |
| case Stmt::NullStmtClass: |
| // - null statements, |
| return true; |
| |
| case Stmt::DeclStmtClass: |
| // - static_assert-declarations |
| // - using-declarations, |
| // - using-directives, |
| // - typedef declarations and alias-declarations that do not define |
| // classes or enumerations, |
| if (!CheckConstexprDeclStmt(SemaRef, Dcl, cast<DeclStmt>(S), Cxx1yLoc, Kind)) |
| return false; |
| return true; |
| |
| case Stmt::ReturnStmtClass: |
| // - and exactly one return statement; |
| if (isa<CXXConstructorDecl>(Dcl)) { |
| // C++1y allows return statements in constexpr constructors. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| return true; |
| } |
| |
| ReturnStmts.push_back(S->getBeginLoc()); |
| return true; |
| |
| case Stmt::CompoundStmtClass: { |
| // C++1y allows compound-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| |
| CompoundStmt *CompStmt = cast<CompoundStmt>(S); |
| for (auto *BodyIt : CompStmt->body()) { |
| if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| } |
| return true; |
| } |
| |
| case Stmt::AttributedStmtClass: |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| return true; |
| |
| case Stmt::IfStmtClass: { |
| // C++1y allows if-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| |
| IfStmt *If = cast<IfStmt>(S); |
| if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| if (If->getElse() && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| return true; |
| } |
| |
| case Stmt::WhileStmtClass: |
| case Stmt::DoStmtClass: |
| case Stmt::ForStmtClass: |
| case Stmt::CXXForRangeStmtClass: |
| case Stmt::ContinueStmtClass: |
| // C++1y allows all of these. We don't allow them as extensions in C++11, |
| // because they don't make sense without variable mutation. |
| if (!SemaRef.getLangOpts().CPlusPlus14) |
| break; |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| for (Stmt *SubStmt : S->children()) |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| return true; |
| |
| case Stmt::SwitchStmtClass: |
| case Stmt::CaseStmtClass: |
| case Stmt::DefaultStmtClass: |
| case Stmt::BreakStmtClass: |
| // C++1y allows switch-statements, and since they don't need variable |
| // mutation, we can reasonably allow them in C++11 as an extension. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| for (Stmt *SubStmt : S->children()) |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| return true; |
| |
| case Stmt::GCCAsmStmtClass: |
| case Stmt::MSAsmStmtClass: |
| // C++2a allows inline assembly statements. |
| case Stmt::CXXTryStmtClass: |
| if (Cxx2aLoc.isInvalid()) |
| Cxx2aLoc = S->getBeginLoc(); |
| for (Stmt *SubStmt : S->children()) { |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| } |
| return true; |
| |
| case Stmt::CXXCatchStmtClass: |
| // Do not bother checking the language mode (already covered by the |
| // try block check). |
| if (!CheckConstexprFunctionStmt(SemaRef, Dcl, |
| cast<CXXCatchStmt>(S)->getHandlerBlock(), |
| ReturnStmts, Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| return true; |
| |
| default: |
| if (!isa<Expr>(S)) |
| break; |
| |
| // C++1y allows expression-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getBeginLoc(); |
| return true; |
| } |
| |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) |
| << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval(); |
| } |
| return false; |
| } |
| |
| /// Check the body for the given constexpr function declaration only contains |
| /// the permitted types of statement. C++11 [dcl.constexpr]p3,p4. |
| /// |
| /// \return true if the body is OK, false if we have found or diagnosed a |
| /// problem. |
| static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl, |
| Stmt *Body, |
| Sema::CheckConstexprKind Kind) { |
| SmallVector<SourceLocation, 4> ReturnStmts; |
| |
| if (isa<CXXTryStmt>(Body)) { |
| // C++11 [dcl.constexpr]p3: |
| // The definition of a constexpr function shall satisfy the following |
| // constraints: [...] |
| // - its function-body shall be = delete, = default, or a |
| // compound-statement |
| // |
| // C++11 [dcl.constexpr]p4: |
| // In the definition of a constexpr constructor, [...] |
| // - its function-body shall not be a function-try-block; |
| // |
| // This restriction is lifted in C++2a, as long as inner statements also |
| // apply the general constexpr rules. |
| switch (Kind) { |
| case Sema::CheckConstexprKind::CheckValid: |
| if (!SemaRef.getLangOpts().CPlusPlus2a) |
| return false; |
| break; |
| |
| case Sema::CheckConstexprKind::Diagnose: |
| SemaRef.Diag(Body->getBeginLoc(), |
| !SemaRef.getLangOpts().CPlusPlus2a |
| ? diag::ext_constexpr_function_try_block_cxx2a |
| : diag::warn_cxx17_compat_constexpr_function_try_block) |
| << isa<CXXConstructorDecl>(Dcl); |
| break; |
| } |
| } |
| |
| // - its function-body shall be [...] a compound-statement that contains only |
| // [... list of cases ...] |
| // |
| // Note that walking the children here is enough to properly check for |
| // CompoundStmt and CXXTryStmt body. |
| SourceLocation Cxx1yLoc, Cxx2aLoc; |
| for (Stmt *SubStmt : Body->children()) { |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc, Cxx2aLoc, Kind)) |
| return false; |
| } |
| |
| if (Kind == Sema::CheckConstexprKind::CheckValid) { |
| // If this is only valid as an extension, report that we don't satisfy the |
| // constraints of the current language. |
| if ((Cxx2aLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus2a) || |
| (Cxx1yLoc.isValid() && !SemaRef.getLangOpts().CPlusPlus17)) |
| return false; |
| } else if (Cxx2aLoc.isValid()) { |
| SemaRef.Diag(Cxx2aLoc, |
| SemaRef.getLangOpts().CPlusPlus2a |
| ? diag::warn_cxx17_compat_constexpr_body_invalid_stmt |
| : diag::ext_constexpr_body_invalid_stmt_cxx2a) |
| << isa<CXXConstructorDecl>(Dcl); |
| } else if (Cxx1yLoc.isValid()) { |
| SemaRef.Diag(Cxx1yLoc, |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_body_invalid_stmt |
| : diag::ext_constexpr_body_invalid_stmt) |
| << isa<CXXConstructorDecl>(Dcl); |
| } |
| |
| if (const CXXConstructorDecl *Constructor |
| = dyn_cast<CXXConstructorDecl>(Dcl)) { |
| const CXXRecordDecl *RD = Constructor->getParent(); |
| // DR1359: |
| // - every non-variant non-static data member and base class sub-object |
| // shall be initialized; |
| // DR1460: |
| // - if the class is a union having variant members, exactly one of them |
| // shall be initialized; |
| if (RD->isUnion()) { |
| if (Constructor->getNumCtorInitializers() == 0 && |
| RD->hasVariantMembers()) { |
| if (Kind == Sema::CheckConstexprKind::Diagnose) { |
| SemaRef.Diag( |
| Dcl->getLocation(), |
| SemaRef.getLangOpts().CPlusPlus2a |
| ? diag::warn_cxx17_compat_constexpr_union_ctor_no_init |
| : diag::ext_constexpr_union_ctor_no_init); |
| } else if (!SemaRef.getLangOpts().CPlusPlus2a) { |
| return false; |
| } |
| } |
| } else if (!Constructor->isDependentContext() && |
| !Constructor->isDelegatingConstructor()) { |
| assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases"); |
| |
| // Skip detailed checking if we have enough initializers, and we would |
| // allow at most one initializer per member. |
| bool AnyAnonStructUnionMembers = false; |
| unsigned Fields = 0; |
| for (CXXRecordDecl::field_iterator I = RD->field_begin(), |
| E = RD->field_end(); I != E; ++I, ++Fields) { |
| if (I->isAnonymousStructOrUnion()) { |
| AnyAnonStructUnionMembers = true; |
| break; |
| } |
| } |
| // DR1460: |
| // - if the class is a union-like class, but is not a union, for each of |
| // its anonymous union members having variant members, exactly one of |
| // them shall be initialized; |
| if (AnyAnonStructUnionMembers || |
| Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) { |
| // Check initialization of non-static data members. Base classes are |
| // always initialized so do not need to be checked. Dependent bases |
| // might not have initializers in the member initializer list. |
| llvm::SmallSet<Decl*, 16> Inits; |
| for (const auto *I: Constructor->inits()) { |
| if (FieldDecl *FD = I->getMember()) |
| Inits.insert(FD); |
| else if (IndirectFieldDecl *ID = I->getIndirectMember()) |
| Inits.insert(ID->chain_begin(), ID->chain_end()); |
| } |
| |
| bool Diagnosed = false; |
| for (auto *I : RD->fields()) |
| if (!CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed, |
| Kind)) |
| return false; |
| } |
| } |
| } else { |
| if (ReturnStmts.empty()) { |
| // C++1y doesn't require constexpr functions to contain a 'return' |
| // statement. We still do, unless the return type might be void, because |
| // otherwise if there's no return statement, the function cannot |
| // be used in a core constant expression. |
| bool OK = SemaRef.getLangOpts().CPlusPlus14 && |
| (Dcl->getReturnType()->isVoidType() || |
| Dcl->getReturnType()->isDependentType()); |
| switch (Kind) { |
| case Sema::CheckConstexprKind::Diagnose: |
| SemaRef.Diag(Dcl->getLocation(), |
| OK ? diag::warn_cxx11_compat_constexpr_body_no_return |
| : diag::err_constexpr_body_no_return) |
| << Dcl->isConsteval(); |
| if (!OK) |
| return false; |
| break; |
| |
| case Sema::CheckConstexprKind::CheckValid: |
| // The formal requirements don't include this rule in C++14, even |
| // though the "must be able to produce a constant expression" rules |
| // still imply it in some cases. |
| if (!SemaRef.getLangOpts().CPlusPlus14) |
| return false; |
| break; |
| } |
| } else if (ReturnStmts.size() > 1) { |
| switch (Kind) { |
| case Sema::CheckConstexprKind::Diagnose: |
| SemaRef.Diag( |
| ReturnStmts.back(), |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_body_multiple_return |
| : diag::ext_constexpr_body_multiple_return); |
| for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I) |
| SemaRef.Diag(ReturnStmts[I], |
| diag::note_constexpr_body_previous_return); |
| break; |
| |
| case Sema::CheckConstexprKind::CheckValid: |
| if (!SemaRef.getLangOpts().CPlusPlus14) |
| return false; |
| break; |
| } |
| } |
| } |
| |
| // C++11 [dcl.constexpr]p5: |
| // if no function argument values exist such that the function invocation |
| // substitution would produce a constant expression, the program is |
| // ill-formed; no diagnostic required. |
| // C++11 [dcl.constexpr]p3: |
| // - every constructor call and implicit conversion used in initializing the |
| // return value shall be one of those allowed in a constant expression. |
| // C++11 [dcl.constexpr]p4: |
| // - every constructor involved in initializing non-static data members and |
| // base class sub-objects shall be a constexpr constructor. |
| // |
| // Note that this rule is distinct from the "requirements for a constexpr |
| // function", so is not checked in CheckValid mode. |
| SmallVector<PartialDiagnosticAt, 8> Diags; |
| if (Kind == Sema::CheckConstexprKind::Diagnose && |
| !Expr::isPotentialConstantExpr(Dcl, Diags)) { |
| SemaRef.Diag(Dcl->getLocation(), |
| diag::ext_constexpr_function_never_constant_expr) |
| << isa<CXXConstructorDecl>(Dcl); |
| for (size_t I = 0, N = Diags.size(); I != N; ++I) |
| SemaRef.Diag(Diags[I].first, Diags[I].second); |
| // Don't return false here: we allow this for compatibility in |
| // system headers. |
| } |
| |
| return true; |
| } |
| |
| /// Get the class that is directly named by the current context. This is the |
| /// class for which an unqualified-id in this scope could name a constructor |
| /// or destructor. |
| /// |
| /// If the scope specifier denotes a class, this will be that class. |
| /// If the scope specifier is empty, this will be the class whose |
| /// member-specification we are currently within. Otherwise, there |
| /// is no such class. |
| CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) { |
| assert(getLangOpts().CPlusPlus && "No class names in C!"); |
| |
| if (SS && SS->isInvalid()) |
| return nullptr; |
| |
| if (SS && SS->isNotEmpty()) { |
| DeclContext *DC = computeDeclContext(*SS, true); |
| return dyn_cast_or_null<CXXRecordDecl>(DC); |
| } |
| |
| return dyn_cast_or_null<CXXRecordDecl>(CurContext); |
| } |
| |
| /// isCurrentClassName - Determine whether the identifier II is the |
| /// name of the class type currently being defined. In the case of |
| /// nested classes, this will only return true if II is the name of |
| /// the innermost class. |
| bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S, |
| const CXXScopeSpec *SS) { |
| CXXRecordDecl *CurDecl = getCurrentClass(S, SS); |
| return CurDecl && &II == CurDecl->getIdentifier(); |
| } |
| |
| /// Determine whether the identifier II is a typo for the name of |
| /// the class type currently being defined. If so, update it to the identifier |
| /// that should have been used. |
| bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) { |
| assert(getLangOpts().CPlusPlus && "No class names in C!"); |
| |
| if (!getLangOpts().SpellChecking) |
| return false; |
| |
| CXXRecordDecl *CurDecl; |
| if (SS && SS->isSet() && !SS->isInvalid()) { |
| DeclContext *DC = computeDeclContext(*SS, true); |
| CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC); |
| } else |
| CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext); |
| |
| if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() && |
| 3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName()) |
| < II->getLength()) { |
| II = CurDecl->getIdentifier(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Determine whether the given class is a base class of the given |
| /// class, including looking at dependent bases. |
| static bool findCircularInheritance(const CXXRecordDecl *Class, |
| const CXXRecordDecl *Current) { |
| SmallVector<const CXXRecordDecl*, 8> Queue; |
| |
| Class = Class->getCanonicalDecl(); |
| while (true) { |
| for (const auto &I : Current->bases()) { |
| CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl(); |
| if (!Base) |
| continue; |
| |
| Base = Base->getDefinition(); |
| if (!Base) |
| continue; |
| |
| if (Base->getCanonicalDecl() == Class) |
| return true; |
| |
| Queue.push_back(Base); |
| } |
| |
| if (Queue.empty()) |
| return false; |
| |
| Current = Queue.pop_back_val(); |
| } |
| |
| return false; |
| } |
| |
| /// Check the validity of a C++ base class specifier. |
| /// |
| /// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics |
| /// and returns NULL otherwise. |
| CXXBaseSpecifier * |
| Sema::CheckBaseSpecifier(CXXRecordDecl *Class, |
| SourceRange SpecifierRange, |
| bool Virtual, AccessSpecifier Access, |
| TypeSourceInfo *TInfo, |
| SourceLocation EllipsisLoc) { |
| QualType BaseType = TInfo->getType(); |
| |
| // C++ [class.union]p1: |
| // A union shall not have base classes. |
| if (Class->isUnion()) { |
| Diag(Class->getLocation(), diag::err_base_clause_on_union) |
| << SpecifierRange; |
| return nullptr; |
| } |
| |
| if (EllipsisLoc.isValid() && |
| !TInfo->getType()->containsUnexpandedParameterPack()) { |
| Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) |
| << TInfo->getTypeLoc().getSourceRange(); |
| EllipsisLoc = SourceLocation(); |
| } |
| |
| SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc(); |
| |
| if (BaseType->isDependentType()) { |
| // Make sure that we don't have circular inheritance among our dependent |
| // bases. For non-dependent bases, the check for completeness below handles |
| // this. |
| if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) { |
| if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() || |
| ((BaseDecl = BaseDecl->getDefinition()) && |
| findCircularInheritance(Class, BaseDecl))) { |
| Diag(BaseLoc, diag::err_circular_inheritance) |
| << BaseType << Context.getTypeDeclType(Class); |
| |
| if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl()) |
| Diag(BaseDecl->getLocation(), diag::note_previous_decl) |
| << BaseType; |
| |
| return nullptr; |
| } |
| } |
| |
| return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, |
| Class->getTagKind() == TTK_Class, |
| Access, TInfo, EllipsisLoc); |
| } |
| |
| // Base specifiers must be record types. |
| if (!BaseType->isRecordType()) { |
| Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange; |
| return nullptr; |
| } |
| |
| // C++ [class.union]p1: |
| // A union shall not be used as a base class. |
| if (BaseType->isUnionType()) { |
| Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange; |
| return nullptr; |
| } |
| |
| // For the MS ABI, propagate DLL attributes to base class templates. |
| if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { |
| if (Attr *ClassAttr = getDLLAttr(Class)) { |
| if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>( |
| BaseType->getAsCXXRecordDecl())) { |
| propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate, |
| BaseLoc); |
| } |
| } |
| } |
| |
| // C++ [class.derived]p2: |
| // The class-name in a base-specifier shall not be an incompletely |
| // defined class. |
| if (RequireCompleteType(BaseLoc, BaseType, |
| diag::err_incomplete_base_class, SpecifierRange)) { |
| Class->setInvalidDecl(); |
| return nullptr; |
| } |
| |
| // If the base class is polymorphic or isn't empty, the new one is/isn't, too. |
| RecordDecl *BaseDecl = BaseType->castAs<RecordType>()->getDecl(); |
| assert(BaseDecl && "Record type has no declaration"); |
| 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"); |
| |
| // Microsoft docs say: |
| // "If a base-class has a code_seg attribute, derived classes must have the |
| // same attribute." |
| const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>(); |
| const auto *DerivedCSA = Class->getAttr<CodeSegAttr>(); |
| if ((DerivedCSA || BaseCSA) && |
| (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) { |
| Diag(Class->getLocation(), diag::err_mismatched_code_seg_base); |
| Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here) |
| << CXXBaseDecl; |
| return nullptr; |
| } |
| |
| // A class which contains a flexible array member is not suitable for use as a |
| // base class: |
| // - If the layout determines that a base comes before another base, |
| // the flexible array member would index into the subsequent base. |
| // - If the layout determines that base comes before the derived class, |
| // the flexible array member would index into the derived class. |
| if (CXXBaseDecl->hasFlexibleArrayMember()) { |
| Diag(BaseLoc, diag::err_base_class_has_flexible_array_member) |
| << CXXBaseDecl->getDeclName(); |
| return nullptr; |
| } |
| |
| // C++ [class]p3: |
| // If a class is marked final and it appears as a base-type-specifier in |
| // base-clause, the program is ill-formed. |
| if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) { |
| Diag(BaseLoc, diag::err_class_marked_final_used_as_base) |
| << CXXBaseDecl->getDeclName() |
| << FA->isSpelledAsSealed(); |
| Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at) |
| << CXXBaseDecl->getDeclName() << FA->getRange(); |
| return nullptr; |
| } |
| |
| if (BaseDecl->isInvalidDecl()) |
| Class->setInvalidDecl(); |
| |
| // Create the base specifier. |
| return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual, |
| Class->getTagKind() == TTK_Class, |
| Access, TInfo, EllipsisLoc); |
| } |
| |
| /// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is |
| /// one entry in the base class list of a class specifier, for |
| /// example: |
| /// class foo : public bar, virtual private baz { |
| /// 'public bar' and 'virtual private baz' are each base-specifiers. |
| BaseResult |
| Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, |
| ParsedAttributes &Attributes, |
| bool Virtual, AccessSpecifier Access, |
| ParsedType basetype, SourceLocation BaseLoc, |
| SourceLocation EllipsisLoc) { |
| if (!classdecl) |
| return true; |
| |
| AdjustDeclIfTemplate(classdecl); |
| CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl); |
| if (!Class) |
| return true; |
| |
| // We haven't yet attached the base specifiers. |
| Class->setIsParsingBaseSpecifiers(); |
| |
| // We do not support any C++11 attributes on base-specifiers yet. |
| // Diagnose any attributes we see. |
| for (const ParsedAttr &AL : Attributes) { |
| if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute) |
| continue; |
| Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute |
| ? (unsigned)diag::warn_unknown_attribute_ignored |
| : (unsigned)diag::err_base_specifier_attribute) |
| << AL; |
| } |
| |
| TypeSourceInfo *TInfo = nullptr; |
| GetTypeFromParser(basetype, &TInfo); |
| |
| if (EllipsisLoc.isInvalid() && |
| DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo, |
| UPPC_BaseType)) |
| return true; |
| |
| if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, |
| Virtual, Access, TInfo, |
| EllipsisLoc)) |
| return BaseSpec; |
| else |
| Class->setInvalidDecl(); |
| |
| return true; |
| } |
| |
| /// Use small set to collect indirect bases. As this is only used |
| /// locally, there's no need to abstract the small size parameter. |
| typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet; |
| |
| /// Recursively add the bases of Type. Don't add Type itself. |
| static void |
| NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set, |
| const QualType &Type) |
| { |
| // Even though the incoming type is a base, it might not be |
| // a class -- it could be a template parm, for instance. |
| if (auto Rec = Type->getAs<RecordType>()) { |
| auto Decl = Rec->getAsCXXRecordDecl(); |
| |
| // Iterate over its bases. |
| for (const auto &BaseSpec : Decl->bases()) { |
| QualType Base = Context.getCanonicalType(BaseSpec.getType()) |
| .getUnqualifiedType(); |
| if (Set.insert(Base).second) |
| // If we've not already seen it, recurse. |
| NoteIndirectBases(Context, Set, Base); |
| } |
| } |
| } |
| |
| /// Performs the actual work of attaching the given base class |
| /// specifiers to a C++ class. |
| 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 |
| // that we can properly diagnose redundant direct base types. Note |
| // that the key is always the unqualified canonical type of the base |
| // class. |
| std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes; |
| |
| // Used to track indirect bases so we can see if a direct base is |
| // ambiguous. |
| IndirectBaseSet IndirectBaseTypes; |
| |
| // Copy non-redundant base specifiers into permanent storage. |
| unsigned NumGoodBases = 0; |
| bool Invalid = false; |
| for (unsigned idx = 0; idx < Bases.size(); ++idx) { |
| QualType NewBaseType |
| = Context.getCanonicalType(Bases[idx]->getType()); |
| NewBaseType = NewBaseType.getLocalUnqualifiedType(); |
| |
| CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType]; |
| if (KnownBase) { |
| // C++ [class.mi]p3: |
| // A class shall not be specified as a direct base class of a |
| // derived class more than once. |
| Diag(Bases[idx]->getBeginLoc(), diag::err_duplicate_base_class) |
| << KnownBase->getType() << Bases[idx]->getSourceRange(); |
| |
| // Delete the duplicate base class specifier; we're going to |
| // overwrite its pointer later. |
| Context.Deallocate(Bases[idx]); |
| |
| Invalid = true; |
| } else { |
| // Okay, add this new base class. |
| KnownBase = Bases[idx]; |
| Bases[NumGoodBases++] = Bases[idx]; |
| |
| // Note this base's direct & indirect bases, if there could be ambiguity. |
| if (Bases.size() > 1) |
| NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType); |
| |
| if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { |
| const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); |
| if (Class->isInterface() && |
| (!RD->isInterfaceLike() || |
| KnownBase->getAccessSpecifier() != AS_public)) { |
| // The Microsoft extension __interface does not permit bases that |
| // are not themselves public interfaces. |
| Diag(KnownBase->getBeginLoc(), diag::err_invalid_base_in_interface) |
| << getRecordDiagFromTagKind(RD->getTagKind()) << RD |
| << RD->getSourceRange(); |
| Invalid = true; |
| } |
| if (RD->hasAttr<WeakAttr>()) |
| Class->addAttr(WeakAttr::CreateImplicit(Context)); |
| } |
| } |
| } |
| |
| // Attach the remaining base class specifiers to the derived class. |
| Class->setBases(Bases.data(), NumGoodBases); |
| |
| // Check that the only base classes that are duplicate are virtual. |
| for (unsigned idx = 0; idx < NumGoodBases; ++idx) { |
| // Check whether this direct base is inaccessible due to ambiguity. |
| QualType BaseType = Bases[idx]->getType(); |
| |
| // Skip all dependent types in templates being used as base specifiers. |
| // Checks below assume that the base specifier is a CXXRecord. |
| if (BaseType->isDependentType()) |
| continue; |
| |
| CanQualType CanonicalBase = Context.getCanonicalType(BaseType) |
| .getUnqualifiedType(); |
| |
| if (IndirectBaseTypes.count(CanonicalBase)) { |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, |
| /*DetectVirtual=*/true); |
| bool found |
| = Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths); |
| assert(found); |
| (void)found; |
| |
| if (Paths.isAmbiguous(CanonicalBase)) |
| Diag(Bases[idx]->getBeginLoc(), diag::warn_inaccessible_base_class) |
| << BaseType << getAmbiguousPathsDisplayString(Paths) |
| << Bases[idx]->getSourceRange(); |
| else |
| assert(Bases[idx]->isVirtual()); |
| } |
| |
| // Delete the base class specifier, since its data has been copied |
| // into the CXXRecordDecl. |
| Context.Deallocate(Bases[idx]); |
| } |
| |
| return Invalid; |
| } |
| |
| /// ActOnBaseSpecifiers - Attach the given base specifiers to the |
| /// class, after checking whether there are any duplicate base |
| /// classes. |
| void Sema::ActOnBaseSpecifiers(Decl *ClassDecl, |
| MutableArrayRef<CXXBaseSpecifier *> Bases) { |
| if (!ClassDecl || Bases.empty()) |
| return; |
| |
| AdjustDeclIfTemplate(ClassDecl); |
| AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases); |
| } |
| |
| /// Determine whether the type \p Derived is a C++ class that is |
| /// derived from the type \p Base. |
| bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) { |
| if (!getLangOpts().CPlusPlus) |
| return false; |
| |
| CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); |
| if (!DerivedRD) |
| return false; |
| |