| //===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // 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/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->getLocStart(), |
| 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->getLocStart(), |
| 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->getLocStart(), |
| 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->getLocStart(), |
| 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: |
| 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->isConstexpr() != Old->isConstexpr()) { |
| Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) |
| << New << New->isConstexpr(); |
| 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; |
| } |
| |
| // FIXME: It's not clear what should happen if multiple declarations of a |
| // deduction guide have different explicitness. For now at least we simply |
| // reject any case where the explicitness changes. |
| auto *NewGuide = dyn_cast<CXXDeductionGuideDecl>(New); |
| if (NewGuide && NewGuide->isExplicitSpecified() != |
| cast<CXXDeductionGuideDecl>(Old)->isExplicitSpecified()) { |
| Diag(New->getLocation(), diag::err_deduction_guide_explicit_mismatch) |
| << NewGuide->isExplicitSpecified(); |
| 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++1z [dcl.dcl]/8: |
| // The decl-specifier-seq shall contain only the type-specifier auto |
| // and cv-qualifiers. |
| auto &DS = D.getDeclSpec(); |
| { |
| SmallVector<StringRef, 8> BadSpecifiers; |
| SmallVector<SourceLocation, 8> BadSpecifierLocs; |
| if (auto SCS = DS.getStorageClassSpec()) { |
| BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS)); |
| BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc()); |
| } |
| if (auto TSCS = DS.getThreadStorageClassSpec()) { |
| BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS)); |
| BadSpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc()); |
| } |
| if (DS.isConstexprSpecified()) { |
| BadSpecifiers.push_back("constexpr"); |
| 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); |
| } |
| // We can't recover from it being declared as a typedef. |
| if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) |
| return nullptr; |
| } |
| |
| 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, it's not tuple-like. |
| if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0)) |
| 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); |
| |
| if (R.empty()) { |
| Diagnoser.diagnoseNotICE(S, Loc, SourceRange()); |
| return IsTupleLike::Error; |
| } |
| |
| 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; |
| UseMemberGet = !MemberGet.empty(); |
| S.FilterAcceptableTemplateNames(MemberGet); |
| } |
| |
| 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.ActOnCallExpr(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.ActOnCallExpr(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); |
| if (E.isInvalid()) |
| return true; |
| RefVD->setInit(E.get()); |
| 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 const CXXRecordDecl *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; |
| 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 RD; |
| } |
| |
| 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 nullptr; |
| } 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 nullptr; |
| } |
| |
| // ... public base class of E. |
| if (BestPath->Access != AS_public) { |
| S.Diag(Loc, diag::err_decomp_decl_non_public_base) |
| << RD << BaseType; |
| for (auto &BS : *BestPath) { |
| if (BS.Base->getAccessSpecifier() != AS_public) { |
| S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path) |
| << (BS.Base->getAccessSpecifier() == AS_protected) |
| << (BS.Base->getAccessSpecifierAsWritten() == AS_none); |
| break; |
| } |
| } |
| return nullptr; |
| } |
| |
| 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 nullptr; |
| } |
| |
| return ClassWithFields; |
| } |
| |
| static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings, |
| ValueDecl *Src, QualType DecompType, |
| const CXXRecordDecl *RD) { |
| CXXCastPath BasePath; |
| RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath); |
| 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 public [...] members, |
| // 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(); |
| if (FD->getAccess() != AS_public) { |
| S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType; |
| |
| // Determine whether the access specifier was explicit. |
| bool Implicit = true; |
| for (const auto *D : RD->decls()) { |
| if (declaresSameEntity(D, FD)) |
| break; |
| if (isa<AccessSpecDecl>(D)) { |
| Implicit = false; |
| break; |
| } |
| } |
| |
| S.Diag(FD->getLocation(), diag::note_access_natural) |
| << (FD->getAccess() == AS_protected) << Implicit; |
| return true; |
| } |
| |
| // 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); |
| } |
| } |
| } |
| } |
| |
| // 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) { |
| 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 (!(*i)->isDependentType() && |
| SemaRef.RequireLiteralType(ParamLoc, *i, |
| diag::err_constexpr_non_literal_param, |
| ArgIndex+1, PD->getSourceRange(), |
| isa<CXXConstructorDecl>(FD))) |
| 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!"); |
| } |
| } |
| |
| // CheckConstexprFunctionDecl - 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 and return false. |
| // |
| // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360. |
| bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { |
| 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; |
| const CXXRecordDecl *RD = MD->getParent(); |
| if (RD->getNumVBases()) { |
| Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) |
| << isa<CXXConstructorDecl>(NewFD) |
| << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases(); |
| for (const auto &I : RD->vbases()) |
| Diag(I.getLocStart(), |
| 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; |
| const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); |
| if (Method && Method->isVirtual()) { |
| 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 (!RT->isDependentType() && |
| RequireLiteralType(NewFD->getLocation(), RT, |
| diag::err_constexpr_non_literal_return)) |
| return false; |
| } |
| |
| // - each of its parameter types shall be a literal type; |
| if (!CheckConstexprParameterTypes(*this, NewFD)) |
| return false; |
| |
| return true; |
| } |
| |
| /// 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) { |
| // 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. |
| 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()) |
| SemaRef.Diag(DS->getLocStart(), |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_type_definition |
| : diag::ext_constexpr_type_definition) |
| << isa<CXXConstructorDecl>(Dcl); |
| 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 for which no initialization is performed. |
| const auto *VD = cast<VarDecl>(DclIt); |
| if (VD->isThisDeclarationADefinition()) { |
| if (VD->isStaticLocal()) { |
| SemaRef.Diag(VD->getLocation(), |
| diag::err_constexpr_local_var_static) |
| << isa<CXXConstructorDecl>(Dcl) |
| << (VD->getTLSKind() == VarDecl::TLS_Dynamic); |
| return false; |
| } |
| if (!VD->getType()->isDependentType() && |
| SemaRef.RequireLiteralType( |
| 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()) { |
| SemaRef.Diag(VD->getLocation(), |
| diag::err_constexpr_local_var_no_init) |
| << isa<CXXConstructorDecl>(Dcl); |
| return false; |
| } |
| } |
| SemaRef.Diag(VD->getLocation(), |
| SemaRef.getLangOpts().CPlusPlus14 |
| ? diag::warn_cxx11_compat_constexpr_local_var |
| : diag::ext_constexpr_local_var) |
| << isa<CXXConstructorDecl>(Dcl); |
| 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->getLocStart(); |
| continue; |
| |
| default: |
| SemaRef.Diag(DS->getLocStart(), diag::err_constexpr_body_invalid_stmt) |
| << isa<CXXConstructorDecl>(Dcl); |
| 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 Set to true if an error is produced. |
| static void CheckConstexprCtorInitializer(Sema &SemaRef, |
| const FunctionDecl *Dcl, |
| FieldDecl *Field, |
| llvm::SmallSet<Decl*, 16> &Inits, |
| bool &Diagnosed) { |
| if (Field->isInvalidDecl()) |
| return; |
| |
| if (Field->isUnnamedBitfield()) |
| return; |
| |
| // 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; |
| |
| if (!Inits.count(Field)) { |
| if (!Diagnosed) { |
| SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init); |
| Diagnosed = true; |
| } |
| SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init); |
| } 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)) |
| CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed); |
| } |
| } |
| |
| /// 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) { |
| // - 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)) |
| 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->getLocStart(); |
| return true; |
| } |
| |
| ReturnStmts.push_back(S->getLocStart()); |
| return true; |
| |
| case Stmt::CompoundStmtClass: { |
| // C++1y allows compound-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getLocStart(); |
| |
| CompoundStmt *CompStmt = cast<CompoundStmt>(S); |
| for (auto *BodyIt : CompStmt->body()) { |
| if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts, |
| Cxx1yLoc)) |
| return false; |
| } |
| return true; |
| } |
| |
| case Stmt::AttributedStmtClass: |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getLocStart(); |
| return true; |
| |
| case Stmt::IfStmtClass: { |
| // C++1y allows if-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getLocStart(); |
| |
| IfStmt *If = cast<IfStmt>(S); |
| if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts, |
| Cxx1yLoc)) |
| return false; |
| if (If->getElse() && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts, |
| Cxx1yLoc)) |
| 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->getLocStart(); |
| for (Stmt *SubStmt : S->children()) |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc)) |
| 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->getLocStart(); |
| for (Stmt *SubStmt : S->children()) |
| if (SubStmt && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts, |
| Cxx1yLoc)) |
| return false; |
| return true; |
| |
| default: |
| if (!isa<Expr>(S)) |
| break; |
| |
| // C++1y allows expression-statements. |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getLocStart(); |
| return true; |
| } |
| |
| SemaRef.Diag(S->getLocStart(), diag::err_constexpr_body_invalid_stmt) |
| << isa<CXXConstructorDecl>(Dcl); |
| 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 diagnosed a problem. |
| bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { |
| 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; |
| Diag(Body->getLocStart(), diag::err_constexpr_function_try_block) |
| << isa<CXXConstructorDecl>(Dcl); |
| return false; |
| } |
| |
| SmallVector<SourceLocation, 4> ReturnStmts; |
| |
| // - its function-body shall be [...] a compound-statement that contains only |
| // [... list of cases ...] |
| CompoundStmt *CompBody = cast<CompoundStmt>(Body); |
| SourceLocation Cxx1yLoc; |
| for (auto *BodyIt : CompBody->body()) { |
| if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc)) |
| return false; |
| } |
| |
| if (Cxx1yLoc.isValid()) |
| Diag(Cxx1yLoc, |
| 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()) { |
| Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init); |
| 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()) |
| CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed); |
| if (Diagnosed) |
| 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 = getLangOpts().CPlusPlus14 && |
| (Dcl->getReturnType()->isVoidType() || |
| Dcl->getReturnType()->isDependentType()); |
| Diag(Dcl->getLocation(), |
| OK ? diag::warn_cxx11_compat_constexpr_body_no_return |
| : diag::err_constexpr_body_no_return); |
| if (!OK) |
| return false; |
| } else if (ReturnStmts.size() > 1) { |
| Diag(ReturnStmts.back(), |
| 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) |
| Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return); |
| } |
| } |
| |
| // 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. |
| SmallVector<PartialDiagnosticAt, 8> Diags; |
| if (!Expr::isPotentialConstantExpr(Dcl, Diags)) { |
| Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr) |
| << isa<CXXConstructorDecl>(Dcl); |
| for (size_t I = 0, N = Diags.size(); I != N; ++I) |
| 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->getAs<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 |
| ? diag::warn_unknown_attribute_ignored |
| : diag::err_base_specifier_attribute) |
| << AL.getName(); |
| } |
| |
| 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]->getLocStart(), |
| 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->getLocStart(), 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]->getLocStart (), 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; |
| |
| CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); |
| if (!BaseRD) |
| return false; |
| |
| // If either the base or the derived type is invalid, don't try to |
| // check whether one is derived from the other. |
| if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl()) |
| return false; |
| |
| // FIXME: In a modules build, do we need the entire path to be visible for us |
| // to be able to use the inheritance relationship? |
| if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) |
| return false; |
| |
| return DerivedRD->isDerivedFrom(BaseRD); |
| } |
| |
| /// 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, |
| CXXBasePaths &Paths) { |
| if (!getLangOpts().CPlusPlus) |
| return false; |
| |
| CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl(); |
| if (!DerivedRD) |
| return false; |
| |
| CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl(); |
| if (!BaseRD) |
| return false; |
| |
| if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined()) |
| return false; |
| |
| return DerivedRD->isDerivedFrom(BaseRD, Paths); |
| } |
| |
| static void BuildBasePathArray(const CXXBasePath &Path, |
| CXXCastPath &BasePathArray) { |
| // We first go backward and check if we have a virtual base. |
| // FIXME: It would be better if CXXBasePath had the base specifier for |
| // the nearest virtual base. |
| unsigned Start = 0; |
| for (unsigned I = Path.size(); I != 0; --I) { |
| if (Path[I - 1].Base->isVirtual()) { |
| Start = I - 1; |
| break; |
| } |
| } |
| |
| // Now add all bases. |
| for (unsigned I = Start, E = Path.size(); I != E; ++I) |
| BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base)); |
| } |
| |
| |
| void Sema::BuildBasePathArray(const CXXBasePaths &Paths, |
| CXXCastPath &BasePathArray) { |
| assert(BasePathArray.empty() && "Base path array must be empty!"); |
| assert(Paths.isRecordingPaths() && "Must record paths!"); |
| return ::BuildBasePathArray(Paths.front(), BasePathArray); |
| } |
| /// CheckDerivedToBaseConversion - Check whether the Derived-to-Base |
| /// conversion (where Derived and Base are class types) is |
| /// well-formed, meaning that the conversion is unambiguous (and |
| /// that all of the base classes are accessible). Returns true |
| /// and emits a diagnostic if the code is ill-formed, returns false |
| /// otherwise. Loc is the location where this routine should point to |
| /// if there is an error, and Range is the source range to highlight |
| /// if there is an error. |
| /// |
| /// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the |
| /// diagnostic for the respective type of error will be suppressed, but the |
| /// check for ill-formed code will still be performed. |
| bool |
| Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, |
| unsigned InaccessibleBaseID, |
| unsigned AmbigiousBaseConvID, |
| SourceLocation Loc, SourceRange Range, |
| DeclarationName Name, |
| CXXCastPath *BasePath, |
| bool IgnoreAccess) { |
| // First, determine whether the path from Derived to Base is |
| // ambiguous. This is slightly more expensive than checking whether |
| // the Derived to Base conversion exists, because here we need to |
| // explore multiple paths to determine if there is an ambiguity. |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, |
| /*DetectVirtual=*/false); |
| bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths); |
| if (!DerivationOkay) |
| return true; |
| |
| const CXXBasePath *Path = nullptr; |
| if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) |
| Path = &Paths.front(); |
| |
| // For MSVC compatibility, check if Derived directly inherits from Base. Clang |
| // warns about this hierarchy under -Winaccessible-base, but MSVC allows the |
| // user to access such bases. |
| if (!Path && getLangOpts().MSVCCompat) { |
| for (const CXXBasePath &PossiblePath : Paths) { |
| if (PossiblePath.size() == 1) { |
| Path = &PossiblePath; |
| if (AmbigiousBaseConvID) |
| Diag(Loc, diag::ext_ms_ambiguous_direct_base) |
| << Base << Derived << Range; |
| break; |
| } |
| } |
| } |
| |
| if (Path) { |
| if (!IgnoreAccess) { |
| // Check that the base class can be accessed. |
| switch ( |
| CheckBaseClassAccess(Loc, Base, Derived, *Path, InaccessibleBaseID)) { |
| case AR_inaccessible: |
| return true; |
| case AR_accessible: |
| case AR_dependent: |
| case AR_delayed: |
| break; |
| } |
| } |
| |
| // Build a base path if necessary. |
| if (BasePath) |
| ::BuildBasePathArray(*Path, *BasePath); |
| return false; |
| } |
| |
| if (AmbigiousBaseConvID) { |
| // We know that the derived-to-base conversion is ambiguous, and |
| // we're going to produce a diagnostic. Perform the derived-to-base |
| // search just one more time to compute all of the possible paths so |
| // that we can print them out. This is more expensive than any of |
| // the previous derived-to-base checks we've done, but at this point |
| // performance isn't as much of an issue. |
| Paths.clear(); |
| Paths.setRecordingPaths(true); |
| bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths); |
| assert(StillOkay && "Can only be used with a derived-to-base conversion"); |
| (void)StillOkay; |
| |
| // Build up a textual representation of the ambiguous paths, e.g., |
| // D -> B -> A, that will be used to illustrate the ambiguous |
| // conversions in the diagnostic. We only print one of the paths |
| // to each base class subobject. |
| std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths); |
| |
| Diag(Loc, AmbigiousBaseConvID) |
| << Derived << Base << PathDisplayStr << Range << Name; |
| } |
| return true; |
| } |
| |
| bool |
| Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, |
| SourceLocation Loc, SourceRange Range, |
| CXXCastPath *BasePath, |
| bool IgnoreAccess) { |
| return CheckDerivedToBaseConversion( |
| Derived, Base, diag::err_upcast_to_inaccessible_base, |
| diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(), |
| BasePath, IgnoreAccess); |
| } |
| |
| |
| /// Builds a string representing ambiguous paths from a |
| /// specific derived class to different subobjects of the same base |
| /// class. |
| /// |
| /// This function builds a string that can be used in error messages |
| /// to show the different paths that one can take through the |
| /// inheritance hierarchy to go from the derived class to different |
| /// subobjects of a base class. The result looks something like this: |
| /// @code |
| /// struct D -> struct B -> struct A |
| /// struct D -> struct C -> struct A |
| /// @endcode |
| std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { |
| std::string PathDisplayStr; |
| std::set<unsigned> DisplayedPaths; |
| for (CXXBasePaths::paths_iterator Path = Paths.begin(); |
| Path != Paths.end(); ++Path) { |
| if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) { |
| // We haven't displayed a path to this particular base |
| // class subobject yet. |
| PathDisplayStr += "\n "; |
| PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString(); |
| for (CXXBasePath::const_iterator Element = Path->begin(); |
| Element != Path->end(); ++Element) |
| PathDisplayStr += " -> " + Element->Base->getType().getAsString(); |
| } |
| } |
| |
| return PathDisplayStr; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // C++ class member Handling |
| //===----------------------------------------------------------------------===// |
| |
| /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. |
| bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, |
| SourceLocation ColonLoc, |
| const ParsedAttributesView &Attrs) { |
| assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); |
| AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, |
| ASLoc, ColonLoc); |
| CurContext->addHiddenDecl(ASDecl); |
| return ProcessAccessDeclAttributeList(ASDecl, Attrs); |
| } |
| |
| /// CheckOverrideControl - Check C++11 override control semantics. |
| void Sema::CheckOverrideControl(NamedDecl *D) { |
| if (D->isInvalidDecl()) |
| return; |
| |
| // We only care about "override" and "final" declarations. |
| if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>()) |
| return; |
| |
| CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); |
| |
| // We can't check dependent instance methods. |
| if (MD && MD->isInstance() && |
| (MD->getParent()->hasAnyDependentBases() || |
| MD->getType()->isDependentType())) |
| return; |
| |
| if (MD && !MD->isVirtual()) { |
| // If we have a non-virtual method, check if if hides a virtual method. |
| // (In that case, it's most likely the method has the wrong type.) |
| SmallVector<CXXMethodDecl *, 8> OverloadedMethods; |
| FindHiddenVirtualMethods(MD, OverloadedMethods); |
| |
| if (!OverloadedMethods.empty()) { |
| if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) { |
| Diag(OA->getLocation(), |
| diag::override_keyword_hides_virtual_member_function) |
| << "override" << (OverloadedMethods.size() > 1); |
| } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) { |
| Diag(FA->getLocation(), |
| diag::override_keyword_hides_virtual_member_function) |
| << (FA->isSpelledAsSealed() ? "sealed" : "final") |
| << (OverloadedMethods.size() > 1); |
| } |
| NoteHiddenVirtualMethods(MD, OverloadedMethods); |
| MD->setInvalidDecl(); |
| return; |
| } |
| // Fall through into the general case diagnostic. |
| // FIXME: We might want to attempt typo correction here. |
| } |
| |
| if (!MD || !MD->isVirtual()) { |
| if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) { |
| Diag(OA->getLocation(), |
| diag::override_keyword_only_allowed_on_virtual_member_functions) |
| << "override" << FixItHint::CreateRemoval(OA->getLocation()); |
| D->dropAttr<OverrideAttr>(); |
| } |
| if (FinalAttr *FA = D->getAttr<FinalAttr>()) { |
| Diag(FA->getLocation(), |
| diag::override_keyword_only_allowed_on_virtual_member_functions) |
| << (FA->isSpelledAsSealed() ? "sealed" : "final") |
| << FixItHint::CreateRemoval(FA->getLocation()); |
| D->dropAttr<FinalAttr>(); |
| } |
| return; |
| } |
| |
| // C++11 [class.virtual]p5: |
| // If a function is marked with the virt-specifier override and |
| // does not override a member function of a base class, the program is |
| // ill-formed. |
| bool HasOverriddenMethods = MD->size_overridden_methods() != 0; |
| if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) |
| Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding) |
| << MD->getDeclName(); |
| } |
| |
| void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { |
| if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>()) |
| return; |
| CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); |
| if (!MD || MD->isImplicit() || MD->hasAttr<FinalAttr>()) |
| return; |
| |
| SourceLocation Loc = MD->getLocation(); |
| SourceLocation SpellingLoc = Loc; |
| if (getSourceManager().isMacroArgExpansion(Loc)) |
| SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin(); |
| SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc); |
| if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc)) |
| return; |
| |
| if (MD->size_overridden_methods() > 0) { |
| unsigned DiagID = isa<CXXDestructorDecl>(MD) |
| ? diag::warn_destructor_marked_not_override_overriding |
| : diag::warn_function_marked_not_override_overriding; |
| Diag(MD->getLocation(), DiagID) << MD->getDeclName(); |
| const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); |
| Diag(OMD->getLocation(), diag::note_overridden_virtual_function); |
| } |
| } |
| |
| /// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member |
| /// function overrides a virtual member function marked 'final', according to |
| /// C++11 [class.virtual]p4. |
| bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, |
| const CXXMethodDecl *Old) { |
| FinalAttr *FA = Old->getAttr<FinalAttr>(); |
| if (!FA) |
| return false; |
| |
| Diag(New->getLocation(), diag::err_final_function_overridden) |
| << New->getDeclName() |
| << FA->isSpelledAsSealed(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function); |
| return true; |
| } |
| |
| static bool InitializationHasSideEffects(const FieldDecl &FD) { |
| const Type *T = FD.getType()->getBaseElementTypeUnsafe(); |
| // FIXME: Destruction of ObjC lifetime types has side-effects. |
| if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl()) |
| return !RD->isCompleteDefinition() || |
| !RD->hasTrivialDefaultConstructor() || |
| !RD->hasTrivialDestructor(); |
| return false; |
| } |
| |
| static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) { |
| ParsedAttributesView::const_iterator Itr = |
| llvm::find_if(list, [](const ParsedAttr &AL) { |
| return AL.isDeclspecPropertyAttribute(); |
| }); |
| if (Itr != list.end()) |
| return &*Itr; |
| return nullptr; |
| } |
| |
| // Check if there is a field shadowing. |
| void Sema::CheckShadowInheritedFields(const SourceLocation &Loc, |
| DeclarationName FieldName, |
| const CXXRecordDecl *RD) { |
| if (Diags.isIgnored(diag::warn_shadow_field, Loc)) |
| return; |
| |
| // To record a shadowed field in a base |
| std::map<CXXRecordDecl*, NamedDecl*> Bases; |
| auto FieldShadowed = [&](const CXXBaseSpecifier *Specifier, |
| CXXBasePath &Path) { |
| const auto Base = Specifier->getType()->getAsCXXRecordDecl(); |
| // Record an ambiguous path directly |
| if (Bases.find(Base) != Bases.end()) |
| return true; |
| for (const auto Field : Base->lookup(FieldName)) { |
| if ((isa<FieldDecl>(Field) || isa<IndirectFieldDecl>(Field)) && |
| Field->getAccess() != AS_private) { |
| assert(Field->getAccess() != AS_none); |
| assert(Bases.find(Base) == Bases.end()); |
| Bases[Base] = Field; |
| return true; |
| } |
| } |
| return false; |
| }; |
| |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, |
| /*DetectVirtual=*/true); |
| if (!RD->lookupInBases(FieldShadowed, Paths)) |
| return; |
| |
| for (const auto &P : Paths) { |
| auto Base = P.back().Base->getType()->getAsCXXRecordDecl(); |
| auto It = Bases.find(Base); |
| // Skip duplicated bases |
| if (It == Bases.end()) |
| continue; |
| auto BaseField = It->second; |
| assert(BaseField->getAccess() != AS_private); |
| if (AS_none != |
| CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) { |
| Diag(Loc, diag::warn_shadow_field) |
| << FieldName << RD << Base; |
| Diag(BaseField->getLocation(), diag::note_shadow_field); |
| Bases.erase(It); |
| } |
| } |
| } |
| |
| /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member |
| /// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the |
| /// bitfield width if there is one, 'InitExpr' specifies the initializer if |
| /// one has been parsed, and 'InitStyle' is set if an in-class initializer is |
| /// present (but parsing it has been deferred). |
| NamedDecl * |
| Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, |
| MultiTemplateParamsArg TemplateParameterLists, |
| Expr *BW, const VirtSpecifiers &VS, |
| InClassInitStyle InitStyle) { |
| const DeclSpec &DS = D.getDeclSpec(); |
| DeclarationNameInfo NameInfo = GetNameForDeclarator(D); |
| DeclarationName Name = NameInfo.getName(); |
| SourceLocation Loc = NameInfo.getLoc(); |
| |
| // For anonymous bitfields, the location should point to the type. |
| if (Loc.isInvalid()) |
| Loc = D.getLocStart(); |
| |
| Expr *BitWidth = static_cast<Expr*>(BW); |
| |
| assert(isa<CXXRecordDecl>(CurContext)); |
| assert(!DS.isFriendSpecified()); |
| |
| bool isFunc = D.isDeclarationOfFunction(); |
| const ParsedAttr *MSPropertyAttr = |
| getMSPropertyAttr(D.getDeclSpec().getAttributes()); |
| |
| if (cast<CXXRecordDecl>(CurContext)->isInterface()) { |
| // The Microsoft extension __interface only permits public member functions |
| // and prohibits constructors, destructors, operators, non-public member |
| // functions, static methods and data members. |
| unsigned InvalidDecl; |
| bool ShowDeclName = true; |
| if (!isFunc && |
| (DS.getStorageClassSpec() == DeclSpec::SCS_typedef || MSPropertyAttr)) |
| InvalidDecl = 0; |
| else if (!isFunc) |
| InvalidDecl = 1; |
| else if (AS != AS_public) |
| InvalidDecl = 2; |
| else if (DS.getStorageClassSpec() == DeclSpec::SCS_static) |
| InvalidDecl = 3; |
| else switch (Name.getNameKind()) { |
| case DeclarationName::CXXConstructorName: |
| InvalidDecl = 4; |
| ShowDeclName = false; |
| break; |
| |
| case DeclarationName::CXXDestructorName: |
| InvalidDecl = 5; |
| ShowDeclName = false; |
| break; |
| |
| case DeclarationName::CXXOperatorName: |
| case DeclarationName::CXXConversionFunctionName: |
| InvalidDecl = 6; |
| break; |
| |
| default: |
| InvalidDecl = 0; |
| break; |
| } |
| |
| if (InvalidDecl) { |
| if (ShowDeclName) |
| Diag(Loc, diag::err_invalid_member_in_interface) |
| << (InvalidDecl-1) << Name; |
| else |
| Diag(Loc, diag::err_invalid_member_in_interface) |
| << (InvalidDecl-1) << ""; |
| return nullptr; |
| } |
| } |
| |
| // C++ 9.2p6: A member shall not be declared to have automatic storage |
| // duration (auto, register) or with the extern storage-class-specifier. |
| // C++ 7.1.1p8: The mutable specifier can be applied only to names of class |
| // data members and cannot be applied to names declared const or static, |
| // and cannot be applied to reference members. |
| switch (DS.getStorageClassSpec()) { |
| case DeclSpec::SCS_unspecified: |
| case DeclSpec::SCS_typedef: |
| case DeclSpec::SCS_static: |
| break; |
| case DeclSpec::SCS_mutable: |
| if (isFunc) { |
| Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function); |
| |
| // FIXME: It would be nicer if the keyword was ignored only for this |
| // declarator. Otherwise we could get follow-up errors. |
| D.getMutableDeclSpec().ClearStorageClassSpecs(); |
| } |
| break; |
| default: |
| Diag(DS.getStorageClassSpecLoc(), |
| diag::err_storageclass_invalid_for_member); |
| D.getMutableDeclSpec().ClearStorageClassSpecs(); |
| break; |
| } |
| |
| bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified || |
| DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && |
| !isFunc); |
| |
| if (DS.isConstexprSpecified() && isInstField) { |
| SemaDiagnosticBuilder B = |
| Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member); |
| SourceLocation ConstexprLoc = DS.getConstexprSpecLoc(); |
| if (InitStyle == ICIS_NoInit) { |
| B << 0 << 0; |
| if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const) |
| B << FixItHint::CreateRemoval(ConstexprLoc); |
| else { |
| B << FixItHint::CreateReplacement(ConstexprLoc, "const"); |
| D.getMutableDeclSpec().ClearConstexprSpec(); |
| const char *PrevSpec; |
| unsigned DiagID; |
| bool Failed = D.getMutableDeclSpec().SetTypeQual( |
| DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts()); |
| (void)Failed; |
| assert(!Failed && "Making a constexpr member const shouldn't fail"); |
| } |
| } else { |
| B << 1; |
| const char *PrevSpec; |
| unsigned DiagID; |
| if (D.getMutableDeclSpec().SetStorageClassSpec( |
| *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID, |
| Context.getPrintingPolicy())) { |
| assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable && |
| "This is the only DeclSpec that should fail to be applied"); |
| B << 1; |
| } else { |
| B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static "); |
| isInstField = false; |
| } |
| } |
| } |
| |
| NamedDecl *Member; |
| if (isInstField) { |
| CXXScopeSpec &SS = D.getCXXScopeSpec(); |
| |
| // Data members must have identifiers for names. |
| if (!Name.isIdentifier()) { |
| Diag(Loc, diag::err_bad_variable_name) |
| << Name; |
| return nullptr; |
| } |
| |
| IdentifierInfo *II = Name.getAsIdentifierInfo(); |
| |
| // Member field could not be with "template" keyword. |
| // So TemplateParameterLists should be empty in this case. |
| if (TemplateParameterLists.size()) { |
| TemplateParameterList* TemplateParams = TemplateParameterLists[0]; |
| if (TemplateParams->size()) { |
| // There is no such thing as a member field template. |
| Diag(D.getIdentifierLoc(), diag::err_template_member) |
| << II |
| << SourceRange(TemplateParams->getTemplateLoc(), |
| TemplateParams->getRAngleLoc()); |
| } else { |
| // There is an extraneous 'template<>' for this member. |
| Diag(TemplateParams->getTemplateLoc(), |
| diag::err_template_member_noparams) |
| << II |
| << SourceRange(TemplateParams->getTemplateLoc(), |
| TemplateParams->getRAngleLoc()); |
| } |
| return nullptr; |
| } |
| |
| if (SS.isSet() && !SS.isInvalid()) { |
| // The user provided a superfluous scope specifier inside a class |
| // definition: |
| // |
| // class X { |
| // int X::member; |
| // }; |
| if (DeclContext *DC = computeDeclContext(SS, false)) |
| diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(), |
| D.getName().getKind() == |
| UnqualifiedIdKind::IK_TemplateId); |
| else |
| Diag(D.getIdentifierLoc(), diag::err_member_qualification) |
| << Name << SS.getRange(); |
| |
| SS.clear(); |
| } |
| |
| if (MSPropertyAttr) { |
| Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D, |
| BitWidth, InitStyle, AS, *MSPropertyAttr); |
| if (!Member) |
| return nullptr; |
| isInstField = false; |
| } else { |
| Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, |
| BitWidth, InitStyle, AS); |
| if (!Member) |
| return nullptr; |
| } |
| |
| CheckShadowInheritedFields(Loc, Name, cast<CXXRecordDecl>(CurContext)); |
| } else { |
| Member = HandleDeclarator(S, D, TemplateParameterLists); |
| if (!Member) |
| return nullptr; |
| |
| // Non-instance-fields can't have a bitfield. |
| if (BitWidth) { |
| if (Member->isInvalidDecl()) { |
| // don't emit another diagnostic. |
| } else if (isa<VarDecl>(Member) || isa<VarTemplateDecl>(Member)) { |
| // C++ 9.6p3: A bit-field shall not be a static member. |
| // "static member 'A' cannot be a bit-field" |
| Diag(Loc, diag::err_static_not_bitfield) |
| << Name << BitWidth->getSourceRange(); |
| } else if (isa<TypedefDecl>(Member)) { |
| // "typedef member 'x' cannot be a bit-field" |
| Diag(Loc, diag::err_typedef_not_bitfield) |
| << Name << BitWidth->getSourceRange(); |
| } else { |
| // A function typedef ("typedef int f(); f a;"). |
| // C++ 9.6p3: A bit-field shall have integral or enumeration type. |
| Diag(Loc, diag::err_not_integral_type_bitfield) |
| << Name << cast<ValueDecl>(Member)->getType() |
| << BitWidth->getSourceRange(); |
| } |
| |
| BitWidth = nullptr; |
| Member->setInvalidDecl(); |
| } |
| |
| NamedDecl *NonTemplateMember = Member; |
| if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) |
| NonTemplateMember = FunTmpl->getTemplatedDecl(); |
| else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) |
| NonTemplateMember = VarTmpl->getTemplatedDecl(); |
| |
| Member->setAccess(AS); |
| |
| // If we have declared a member function template or static data member |
| // template, set the access of the templated declaration as well. |
| if (NonTemplateMember != Member) |
| NonTemplateMember->setAccess(AS); |
| |
| // C++ [temp.deduct.guide]p3: |
| // A deduction guide [...] for a member class template [shall be |
| // declared] with the same access [as the template]. |
| if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) { |
| auto *TD = DG->getDeducedTemplate(); |
| if (AS != TD->getAccess()) { |
| Diag(DG->getLocStart(), diag::err_deduction_guide_wrong_access); |
| Diag(TD->getLocStart(), diag::note_deduction_guide_template_access) |
| << TD->getAccess(); |
| const AccessSpecDecl *LastAccessSpec = nullptr; |
| for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) { |
| if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D)) |
| LastAccessSpec = AccessSpec; |
| } |
| assert(LastAccessSpec && "differing access with no access specifier"); |
| Diag(LastAccessSpec->getLocStart(), diag::note_deduction_guide_access) |
| << AS; |
| } |
| } |
| } |
| |
| if (VS.isOverrideSpecified()) |
| Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0)); |
| if (VS.isFinalSpecified()) |
| Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context, |
| VS.isFinalSpelledSealed())); |
| |
| if (VS.getLastLocation().isValid()) { |
| // Update the end location of a method that has a virt-specifiers. |
| if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member)) |
| MD->setRangeEnd(VS.getLastLocation()); |
| } |
| |
| CheckOverrideControl(Member); |
| |
| assert((Name || isInstField) && "No identifier for non-field ?"); |
| |
| if (isInstField) { |
| FieldDecl *FD = cast<FieldDecl>(Member); |
| FieldCollector->Add(FD); |
| |
| if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) { |
| // Remember all explicit private FieldDecls that have a name, no side |
| // effects and are not part of a dependent type declaration. |
| if (!FD->isImplicit() && FD->getDeclName() && |
| FD->getAccess() == AS_private && |
| !FD->hasAttr<UnusedAttr>() && |
| !FD->getParent()->isDependentContext() && |
| !InitializationHasSideEffects(*FD)) |
| UnusedPrivateFields.insert(FD); |
| } |
| } |
| |
| return Member; |
| } |
| |
| namespace { |
| class UninitializedFieldVisitor |
| : public EvaluatedExprVisitor<UninitializedFieldVisitor> { |
| Sema &S; |
| // List of Decls to generate a warning on. Also remove Decls that become |
| // initialized. |
| llvm::SmallPtrSetImpl<ValueDecl*> &Decls; |
| // List of base classes of the record. Classes are removed after their |
| // initializers. |
| llvm::SmallPtrSetImpl<QualType> &BaseClasses; |
| // Vector of decls to be removed from the Decl set prior to visiting the |
| // nodes. These Decls may have been initialized in the prior initializer. |
| llvm::SmallVector<ValueDecl*, 4> DeclsToRemove; |
| // If non-null, add a note to the warning pointing back to the constructor. |
| const CXXConstructorDecl *Constructor; |
| // Variables to hold state when processing an initializer list. When |
| // InitList is true, special case initialization of FieldDecls matching |
| // InitListFieldDecl. |
| bool InitList; |
| FieldDecl *InitListFieldDecl; |
| llvm::SmallVector<unsigned, 4> InitFieldIndex; |
| |
| public: |
| typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; |
| UninitializedFieldVisitor(Sema &S, |
| llvm::SmallPtrSetImpl<ValueDecl*> &Decls, |
| llvm::SmallPtrSetImpl<QualType> &BaseClasses) |
| : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses), |
| Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {} |
| |
| // Returns true if the use of ME is not an uninitialized use. |
| bool IsInitListMemberExprInitialized(MemberExpr *ME, |
| bool CheckReferenceOnly) { |
| llvm::SmallVector<FieldDecl*, 4> Fields; |
| bool ReferenceField = false; |
| while (ME) { |
| FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); |
| if (!FD) |
| return false; |
| Fields.push_back(FD); |
| if (FD->getType()->isReferenceType()) |
| ReferenceField = true; |
| ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts()); |
| } |
| |
| // Binding a reference to an unintialized field is not an |
| // uninitialized use. |
| if (CheckReferenceOnly && !ReferenceField) |
| return true; |
| |
| llvm::SmallVector<unsigned, 4> UsedFieldIndex; |
| // Discard the first field since it is the field decl that is being |
| // initialized. |
| for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) { |
| UsedFieldIndex.push_back((*I)->getFieldIndex()); |
| } |
| |
| for (auto UsedIter = UsedFieldIndex.begin(), |
| UsedEnd = UsedFieldIndex.end(), |
| OrigIter = InitFieldIndex.begin(), |
| OrigEnd = InitFieldIndex.end(); |
| UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) { |
| if (*UsedIter < *OrigIter) |
| return true; |
| if (*UsedIter > *OrigIter) |
| break; |
| } |
| |
| return false; |
| } |
| |
| void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly, |
| bool AddressOf) { |
| if (isa<EnumConstantDecl>(ME->getMemberDecl())) |
| return; |
| |
| // FieldME is the inner-most MemberExpr that is not an anonymous struct |
| // or union. |
| MemberExpr *FieldME = ME; |
| |
| bool AllPODFields = FieldME->getType().isPODType(S.Context); |
| |
| Expr *Base = ME; |
| while (MemberExpr *SubME = |
| dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) { |
| |
| if (isa<VarDecl>(SubME->getMemberDecl())) |
| return; |
| |
| if (FieldDecl *FD = dyn_cast<FieldDecl>(SubME->getMemberDecl())) |
| if (!FD->isAnonymousStructOrUnion()) |
| FieldME = SubME; |
| |
| if (!FieldME->getType().isPODType(S.Context)) |
| AllPODFields = false; |
| |
| Base = SubME->getBase(); |
| } |
| |
| if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts())) |
| return; |
| |
| if (AddressOf && AllPODFields) |
| return; |
| |
| ValueDecl* FoundVD = FieldME->getMemberDecl(); |
| |
| if (ImplicitCastExpr *BaseCast = dyn_cast<ImplicitCastExpr>(Base)) { |
| while (isa<ImplicitCastExpr>(BaseCast->getSubExpr())) { |
| BaseCast = cast<ImplicitCastExpr>(BaseCast->getSubExpr()); |
| } |
| |
| if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) { |
| QualType T = BaseCast->getType(); |
| if (T->isPointerType() && |
| BaseClasses.count(T->getPointeeType())) { |
| S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit) |
| << T->getPointeeType() << FoundVD; |
| } |
| } |
| } |
| |
| if (!Decls.count(FoundVD)) |
| return; |
| |
| const bool IsReference = FoundVD->getType()->isReferenceType(); |
| |
| if (InitList && !AddressOf && FoundVD == InitListFieldDecl) { |
| // Special checking for initializer lists. |
| if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) { |
| return; |
| } |
| } else { |
| // Prevent double warnings on use of unbounded references. |
| if (CheckReferenceOnly && !IsReference) |
| return; |
| } |
| |
| unsigned diag = IsReference |
| ? diag::warn_reference_field_is_uninit |
| : diag::warn_field_is_uninit; |
| S.Diag(FieldME->getExprLoc(), diag) << FoundVD; |
| if (Constructor) |
| S.Diag(Constructor->getLocation(), |
| diag::note_uninit_in_this_constructor) |
| << (Constructor->isDefaultConstructor() && Constructor->isImplicit()); |
| |
| } |
| |
| void HandleValue(Expr *E, bool AddressOf) { |
| E = E->IgnoreParens(); |
| |
| if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { |
| HandleMemberExpr(ME, false /*CheckReferenceOnly*/, |
| AddressOf /*AddressOf*/); |
| return; |
| } |
| |
| if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { |
| Visit(CO->getCond()); |
| HandleValue(CO->getTrueExpr(), AddressOf); |
| HandleValue(CO->getFalseExpr(), AddressOf); |
| return; |
| } |
| |
| if (BinaryConditionalOperator *BCO = |
| dyn_cast<BinaryConditionalOperator>(E)) { |
| Visit(BCO->getCond()); |
| HandleValue(BCO->getFalseExpr(), AddressOf); |
| return; |
| } |
| |
| if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) { |
| HandleValue(OVE->getSourceExpr(), AddressOf); |
| return; |
| } |
| |
| if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { |
| switch (BO->getOpcode()) { |
| default: |
| break; |
| case(BO_PtrMemD): |
| case(BO_PtrMemI): |
| HandleValue(BO->getLHS(), AddressOf); |
| Visit(BO->getRHS()); |
| return; |
| case(BO_Comma): |
| Visit(BO->getLHS()); |
| HandleValue(BO->getRHS(), AddressOf); |
| return; |
| } |
| } |
| |
| Visit(E); |
| } |
| |
| void CheckInitListExpr(InitListExpr *ILE) { |
| InitFieldIndex.push_back(0); |
| for (auto Child : ILE->children()) { |
| if (InitListExpr *SubList = dyn_cast<InitListExpr>(Child)) { |
| CheckInitListExpr(SubList); |
| } else { |
| Visit(Child); |
| } |
| ++InitFieldIndex.back(); |
| } |
| InitFieldIndex.pop_back(); |
| } |
| |
| void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor, |
| FieldDecl *Field, const Type *BaseClass) { |
| // Remove Decls that may have been initialized in the previous |
| // initializer. |
| for (ValueDecl* VD : DeclsToRemove) |
| Decls.erase(VD); |
| DeclsToRemove.clear(); |
| |
| Constructor = FieldConstructor; |
| InitListExpr *ILE = dyn_cast<InitListExpr>(E); |
| |
| if (ILE && Field) { |
| InitList = true; |
| InitListFieldDecl = Field; |
| InitFieldIndex.clear(); |
| CheckInitListExpr(ILE); |
| } else { |
| InitList = false; |
| Visit(E); |
| } |
| |
| if (Field) |
| Decls.erase(Field); |
| if (BaseClass) |
| BaseClasses.erase(BaseClass->getCanonicalTypeInternal()); |
| } |
| |
| void VisitMemberExpr(MemberExpr *ME) { |
| // All uses of unbounded reference fields will warn. |
| HandleMemberExpr(ME, true /*CheckReferenceOnly*/, false /*AddressOf*/); |
| } |
| |
| void VisitImplicitCastExpr(ImplicitCastExpr *E) { |
| if (E->getCastKind() == CK_LValueToRValue) { |
| HandleValue(E->getSubExpr(), false /*AddressOf*/); |
| return; |
| } |
| |
| Inherited::VisitImplicitCastExpr(E); |
| } |
| |
| void VisitCXXConstructExpr(CXXConstructExpr *E) { |
| if (E->getConstructor()->isCopyConstructor()) { |
| Expr *ArgExpr = E->getArg(0); |
| if (InitListExpr *ILE = dyn_cast<InitListExpr>(ArgExpr)) |
| if (ILE->getNumInits() == 1) |
| ArgExpr = ILE->getInit(0); |
| if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr)) |
| if (ICE->getCastKind() == CK_NoOp) |
| ArgExpr = ICE->getSubExpr(); |
| HandleValue(ArgExpr, false /*AddressOf*/); |
| return; |
| } |
| Inherited::VisitCXXConstructExpr(E); |
| } |
| |
| void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { |
| Expr *Callee = E->getCallee(); |
| if (isa<MemberExpr>(Callee)) { |
| HandleValue(Callee, false /*AddressOf*/); |
| for (auto Arg : E->arguments()) |
| Visit(Arg); |
| return; |
| } |
| |
| Inherited::VisitCXXMemberCallExpr(E); |
| } |
| |
| void VisitCallExpr(CallExpr *E) { |
| // Treat std::move as a use. |
| if (E->isCallToStdMove()) { |
| HandleValue(E->getArg(0), /*AddressOf=*/false); |
| return; |
| } |
| |
| Inherited::VisitCallExpr(E); |
| } |
| |
| void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { |
| Expr *Callee = E->getCallee(); |
| |
| if (isa<UnresolvedLookupExpr>(Callee)) |
| return Inherited::VisitCXXOperatorCallExpr(E); |
| |
| Visit(Callee); |
| for (auto Arg : E->arguments()) |
| HandleValue(Arg->IgnoreParenImpCasts(), false /*AddressOf*/); |
| } |
| |
| void VisitBinaryOperator(BinaryOperator *E) { |
| // If a field assignment is detected, remove the field from the |
| // uninitiailized field set. |
| if (E->getOpcode() == BO_Assign) |
| if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS())) |
| if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) |
| if (!FD->getType()->isReferenceType()) |
| DeclsToRemove.push_back(FD); |
| |
| if (E->isCompoundAssignmentOp()) { |
| HandleValue(E->getLHS(), false /*AddressOf*/); |
| Visit(E->getRHS()); |
| return; |
| } |
| |
| Inherited::VisitBinaryOperator(E); |
| } |
| |
| void VisitUnaryOperator(UnaryOperator *E) { |
| if (E->isIncrementDecrementOp()) { |
| HandleValue(E->getSubExpr(), false /*AddressOf*/); |
| return; |
| } |
| if (E->getOpcode() == UO_AddrOf) { |
| if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr())) { |
| HandleValue(ME->getBase(), true /*AddressOf*/); |
| return; |
| } |
| } |
| |
| Inherited::VisitUnaryOperator(E); |
| } |
| }; |
| |
| // Diagnose value-uses of fields to initialize themselves, e.g. |
| // foo(foo) |
| // where foo is not also a parameter to the constructor. |
| // Also diagnose across field uninitialized use such as |
| // x(y), y(x) |
| // TODO: implement -Wuninitialized and fold this into that framework. |
| static void DiagnoseUninitializedFields( |
| Sema &SemaRef, const CXXConstructorDecl *Constructor) { |
| |
| if (SemaRef.getDiagnostics().isIgnored(diag::warn_field_is_uninit, |
| Constructor->getLocation())) { |
| return; |
| } |
| |
| if (Constructor->isInvalidDecl()) |
| return; |
| |
| const CXXRecordDecl *RD = Constructor->getParent(); |
| |
| if (RD->getDescribedClassTemplate()) |
| return; |
| |
| // Holds fields that are uninitialized. |
| llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields; |
| |
| // At the beginning, all fields are uninitialized. |
| for (auto *I : RD->decls()) { |
| if (auto *FD = dyn_cast<FieldDecl>(I)) { |
| UninitializedFields.insert(FD); |
| } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(I)) { |
| UninitializedFields.insert(IFD->getAnonField()); |
| } |
| } |
| |
| llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses; |
| for (auto I : RD->bases()) |
| UninitializedBaseClasses.insert(I.getType().getCanonicalType()); |
| |
| if (UninitializedFields.empty() && UninitializedBaseClasses.empty()) |
| return; |
| |
| UninitializedFieldVisitor UninitializedChecker(SemaRef, |
| UninitializedFields, |
| UninitializedBaseClasses); |
| |
| for (const auto *FieldInit : Constructor->inits()) { |
| if (UninitializedFields.empty() && UninitializedBaseClasses.empty()) |
| break; |
| |
| Expr *InitExpr = FieldInit->getInit(); |
| if (!InitExpr) |
| continue; |
| |
| if (CXXDefaultInitExpr *Default = |
| dyn_cast<CXXDefaultInitExpr>(InitExpr)) { |
| InitExpr = Default->getExpr(); |
| if (!InitExpr) |
| continue; |
| // In class initializers will point to the constructor. |
| UninitializedChecker.CheckInitializer(InitExpr, Constructor, |
| FieldInit->getAnyMember(), |
| FieldInit->getBaseClass()); |
| } else { |
| UninitializedChecker.CheckInitializer(InitExpr, nullptr, |
| FieldInit->getAnyMember(), |
| FieldInit->getBaseClass()); |
| } |
| } |
| } |
| } // namespace |
| |
| /// Enter a new C++ default initializer scope. After calling this, the |
| /// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if |
| /// parsing or instantiating the initializer failed. |
| void Sema::ActOnStartCXXInClassMemberInitializer() { |
| // Create a synthetic function scope to represent the call to the constructor |
| // that notionally surrounds a use of this initializer. |
| PushFunctionScope(); |
| } |
| |
| /// This is invoked after parsing an in-class initializer for a |
| /// non-static C++ class member, and after instantiating an in-class initializer |
| /// in a class template. Such actions are deferred until the class is complete. |
| void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, |
| SourceLocation InitLoc, |
| Expr *InitExpr) { |
| // Pop the notional constructor scope we created earlier. |
| PopFunctionScopeInfo(nullptr, D); |
| |
| FieldDecl *FD = dyn_cast<FieldDecl>(D); |
| assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) && |
| "must set init style when field is created"); |
| |
| if (!InitExpr) { |
| D->setInvalidDecl(); |
| if (FD) |
| FD->removeInClassInitializer(); |
| return; |
| } |
| |
| if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) { |
| FD->setInvalidDecl(); |
| FD->removeInClassInitializer(); |
| return; |
| } |
| |
| ExprResult Init = InitExpr; |
| if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) { |
| InitializedEntity Entity = |
| InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD); |
| InitializationKind Kind = |
| FD->getInClassInitStyle() == ICIS_ListInit |
| ? InitializationKind::CreateDirectList(InitExpr->getLocStart(), |
| InitExpr->getLocStart(), |
| InitExpr->getLocEnd()) |
| : InitializationKind::CreateCopy(InitExpr->getLocStart(), InitLoc); |
| InitializationSequence Seq(*this, Entity, Kind, InitExpr); |
| Init = Seq.Perform(*this, Entity, Kind, InitExpr); |
| if (Init.isInvalid()) { |
| FD->setInvalidDecl(); |
| return; |
| } |
| } |
| |
| // C++11 [class.base.init]p7: |
| // The initialization of each base and member constitutes a |
| // full-expression. |
| Init = ActOnFinishFullExpr(Init.get(), InitLoc); |
| if (Init.isInvalid()) { |
| FD->setInvalidDecl(); |
| return; |
| } |
| |
| InitExpr = Init.get(); |
| |
| FD->setInClassInitializer(InitExpr); |
| } |
| |
| /// Find the direct and/or virtual base specifiers that |
| /// correspond to the given base type, for use in base initialization |
| /// within a constructor. |
| static bool FindBaseInitializer(Sema &SemaRef, |
| CXXRecordDecl *ClassDecl, |
| QualType BaseType, |
| const CXXBaseSpecifier *&DirectBaseSpec, |
| const CXXBaseSpecifier *&VirtualBaseSpec) { |
| // First, check for a direct base class. |
| DirectBaseSpec = nullptr; |
| for (const auto &Base : ClassDecl->bases()) { |
| if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) { |
| // We found a direct base of this type. That's what we're |
| // initializing. |
| DirectBaseSpec = &Base; |
| break; |
| } |
| } |
| |
| // Check for a virtual base class. |
| // FIXME: We might be able to short-circuit this if we know in advance that |
| // there are no virtual bases. |
| VirtualBaseSpec = nullptr; |
| if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) { |
| // We haven't found a base yet; search the class hierarchy for a |
| // virtual base class. |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true, |
| /*DetectVirtual=*/false); |
| if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(), |
| SemaRef.Context.getTypeDeclType(ClassDecl), |
| BaseType, Paths)) { |
| for (CXXBasePaths::paths_iterator Path = Paths.begin(); |
| Path != Paths.end(); ++Path) { |
| if (Path->back().Base->isVirtual()) { |
| VirtualBaseSpec = Path->back().Base; |
| break; |
| } |
| } |
| } |
| } |
| |
| return DirectBaseSpec || VirtualBaseSpec; |
| } |
| |
| /// Handle a C++ member initializer using braced-init-list syntax. |
| MemInitResult |
| Sema::ActOnMemInitializer(Decl *ConstructorD, |
| Scope *S, |
| CXXScopeSpec &SS, |
| IdentifierInfo *MemberOrBase, |
| ParsedType TemplateTypeTy, |
| const DeclSpec &DS, |
| SourceLocation IdLoc, |
| Expr *InitList, |
| SourceLocation EllipsisLoc) { |
| return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, |
| DS, IdLoc, InitList, |
| EllipsisLoc); |
| } |
| |
| /// Handle a C++ member initializer using parentheses syntax. |
| MemInitResult |
| Sema::ActOnMemInitializer(Decl *ConstructorD, |
| Scope *S, |
| CXXScopeSpec &SS, |
| IdentifierInfo *MemberOrBase, |
| ParsedType TemplateTypeTy, |
| const DeclSpec &DS, |
| SourceLocation IdLoc, |
| SourceLocation LParenLoc, |
| ArrayRef<Expr *> Args, |
| SourceLocation RParenLoc, |
| SourceLocation EllipsisLoc) { |
| Expr *List = new (Context) ParenListExpr(Context, LParenLoc, |
| Args, RParenLoc); |
| return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, |
| DS, IdLoc, List, EllipsisLoc); |
| } |
| |
| namespace { |
| |
| // Callback to only accept typo corrections that can be a valid C++ member |
| // intializer: either a non-static field member or a base class. |
| class MemInitializerValidatorCCC : public CorrectionCandidateCallback { |
| public: |
| explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl) |
| : ClassDecl(ClassDecl) {} |
| |
| bool ValidateCandidate(const TypoCorrection &candidate) override { |
| if (NamedDecl *ND = candidate.getCorrectionDecl()) { |
| if (FieldDecl *Member = dyn_cast<FieldDecl>(ND)) |
| return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl); |
| return isa<TypeDecl>(ND); |
| } |
| return false; |
| } |
| |
| private: |
| CXXRecordDecl *ClassDecl; |
| }; |
| |
| } |
| |
| /// Handle a C++ member initializer. |
| MemInitResult |
| Sema::BuildMemInitializer(Decl *ConstructorD, |
| Scope *S, |
| CXXScopeSpec &SS, |
| IdentifierInfo *MemberOrBase, |
| ParsedType TemplateTypeTy, |
| const DeclSpec &DS, |
| SourceLocation IdLoc, |
| Expr *Init, |
| SourceLocation EllipsisLoc) { |
| ExprResult Res = CorrectDelayedTyposInExpr(Init); |
| if (!Res.isUsable()) |
| return true; |
| Init = Res.get(); |
| |
| if (!ConstructorD) |
| return true; |
| |
| AdjustDeclIfTemplate(ConstructorD); |
| |
| CXXConstructorDecl *Constructor |
| = dyn_cast<CXXConstructorDecl>(ConstructorD); |
| if (!Constructor) { |
| // The user wrote a constructor initializer on a function that is |
| // not a C++ constructor. Ignore the error for now, because we may |
| // have more member initializers coming; we'll diagnose it just |
| // once in ActOnMemInitializers. |
| return true; |
| } |
| |
| CXXRecordDecl *ClassDecl = Constructor->getParent(); |
| |
| // C++ [class.base.init]p2: |
| // Names in a mem-initializer-id are looked up in the scope of the |
| // constructor's class and, if not found in that scope, are looked |
| // up in the scope containing the constructor's definition. |
| // [Note: if the constructor's class contains a member with the |
| // same name as a direct or virtual base class of the class, a |
| // mem-initializer-id naming the member or base class and composed |
| // of a single identifier refers to the class member. A |
| // mem-initializer-id for the hidden base class may be specified |
| // using a qualified name. ] |
| if (!SS.getScopeRep() && !TemplateTypeTy) { |
| // Look for a member, first. |
| DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase); |
| if (!Result.empty()) { |
| ValueDecl *Member; |
| if ((Member = dyn_cast<FieldDecl>(Result.front())) || |
| (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) { |
| if (EllipsisLoc.isValid()) |
| Diag(EllipsisLoc, diag::err_pack_expansion_member_init) |
| << MemberOrBase |
| << SourceRange(IdLoc, Init->getSourceRange().getEnd()); |
| |
| return BuildMemberInitializer(Member, Init, IdLoc); |
| } |
| } |
| } |
| // It didn't name a member, so see if it names a class. |
| QualType BaseType; |
| TypeSourceInfo *TInfo = nullptr; |
| |
| if (TemplateTypeTy) { |
| BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); |
| } else if (DS.getTypeSpecType() == TST_decltype) { |
| BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); |
| } else if (DS.getTypeSpecType() == TST_decltype_auto) { |
| Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); |
| return true; |
| } else { |
| LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName); |
| LookupParsedName(R, S, &SS); |
| |
| TypeDecl *TyD = R.getAsSingle<TypeDecl>(); |
| if (!TyD) { |
| if (R.isAmbiguous()) return true; |
| |
| // We don't want access-control diagnostics here. |
| R.suppressDiagnostics(); |
| |
| if (SS.isSet() && isDependentScopeSpecifier(SS)) { |
| bool NotUnknownSpecialization = false; |
| DeclContext *DC = computeDeclContext(SS, false); |
| if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC)) |
| NotUnknownSpecialization = !Record->hasAnyDependentBases(); |
| |
| if (!NotUnknownSpecialization) { |
| // When the scope specifier can refer to a member of an unknown |
| // specialization, we take it as a type name. |
| BaseType = CheckTypenameType(ETK_None, SourceLocation(), |
| SS.getWithLocInContext(Context), |
| *MemberOrBase, IdLoc); |
| if (BaseType.isNull()) |
| return true; |
| |
| TInfo = Context.CreateTypeSourceInfo(BaseType); |
| DependentNameTypeLoc TL = |
| TInfo->getTypeLoc().castAs<DependentNameTypeLoc>(); |
| if (!TL.isNull()) { |
| TL.setNameLoc(IdLoc); |
| TL.setElaboratedKeywordLoc(SourceLocation()); |
| TL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| } |
| |
| R.clear(); |
| R.setLookupName(MemberOrBase); |
| } |
| } |
| |
| // If no results were found, try to correct typos. |
| TypoCorrection Corr; |
| if (R.empty() && BaseType.isNull() && |
| (Corr = CorrectTypo( |
| R.getLookupNameInfo(), R.getLookupKind(), S, &SS, |
| llvm::make_unique<MemInitializerValidatorCCC>(ClassDecl), |
| CTK_ErrorRecovery, ClassDecl))) { |
| if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) { |
| // We have found a non-static data member with a similar |
| // name to what was typed; complain and initialize that |
| // member. |
| diagnoseTypo(Corr, |
| PDiag(diag::err_mem_init_not_member_or_class_suggest) |
| << MemberOrBase << true); |
| return BuildMemberInitializer(Member, Init, IdLoc); |
| } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { |
| const CXXBaseSpecifier *DirectBaseSpec; |
| const CXXBaseSpecifier *VirtualBaseSpec; |
| if (FindBaseInitializer(*this, ClassDecl, |
| Context.getTypeDeclType(Type), |
| DirectBaseSpec, VirtualBaseSpec)) { |
| // We have found a direct or virtual base class with a |
| // similar name to what was typed; complain and initialize |
| // that base class. |
| diagnoseTypo(Corr, |
| PDiag(diag::err_mem_init_not_member_or_class_suggest) |
| << MemberOrBase << false, |
| PDiag() /*Suppress note, we provide our own.*/); |
| |
| const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec |
| : VirtualBaseSpec; |
| Diag(BaseSpec->getLocStart(), |
| diag::note_base_class_specified_here) |
| << BaseSpec->getType() |
| << BaseSpec->getSourceRange(); |
| |
| TyD = Type; |
| } |
| } |
| } |
| |
| if (!TyD && BaseType.isNull()) { |
| Diag(IdLoc, diag::err_mem_init_not_member_or_class) |
| << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); |
| return true; |
| } |
| } |
| |
| if (BaseType.isNull()) { |
| BaseType = Context.getTypeDeclType(TyD); |
| MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false); |
| if (SS.isSet()) { |
| BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), |
| BaseType); |
| TInfo = Context.CreateTypeSourceInfo(BaseType); |
| ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>(); |
| TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc); |
| TL.setElaboratedKeywordLoc(SourceLocation()); |
| TL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| } |
| } |
| } |
| |
| if (!TInfo) |
| TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); |
| |
| return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); |
| } |
| |
| MemInitResult |
| Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, |
| SourceLocation IdLoc) { |
| FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); |
| IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); |
| assert((DirectMember || IndirectMember) && |
| "Member must be a FieldDecl or IndirectFieldDecl"); |
| |
| if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) |
| return true; |
| |
| if (Member->isInvalidDecl()) |
| return true; |
| |
| MultiExprArg Args; |
| if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { |
| Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); |
| } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) { |
| Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); |
| } else { |
| // Template instantiation doesn't reconstruct ParenListExprs for us. |
| Args = Init; |
| } |
| |
| SourceRange InitRange = Init->getSourceRange(); |
| |
| if (Member->getType()->isDependentType() || Init->isTypeDependent()) { |
| // Can't check initialization for a member of dependent type or when |
| // any of the arguments are type-dependent expressions. |
| DiscardCleanupsInEvaluationContext(); |
| } else { |
| bool InitList = false; |
| if (isa<InitListExpr>(Init)) { |
| InitList = true; |
| Args = Init; |
| } |
| |
| // Initialize the member. |
| InitializedEntity MemberEntity = |
| DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr) |
| : InitializedEntity::InitializeMember(IndirectMember, |
| nullptr); |
| InitializationKind Kind = |
| InitList ? InitializationKind::CreateDirectList( |
| IdLoc, Init->getLocStart(), Init->getLocEnd()) |
| : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), |
| InitRange.getEnd()); |
| |
| InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); |
| ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, |
| nullptr); |
| if (MemberInit.isInvalid()) |
| return true; |
| |
| // C++11 [class.base.init]p7: |
| // The initialization of each base and member constitutes a |
| // full-expression. |
| MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); |
| if (MemberInit.isInvalid()) |
| return true; |
| |
| Init = MemberInit.get(); |
| } |
| |
| if (DirectMember) { |
| return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, |
| InitRange.getBegin(), Init, |
| InitRange.getEnd()); |
| } else { |
| return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, |
| InitRange.getBegin(), Init, |
| InitRange.getEnd()); |
| } |
| } |
| |
| MemInitResult |
| Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, |
| CXXRecordDecl *ClassDecl) { |
| SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); |
| if (!LangOpts.CPlusPlus11) |
| return Diag(NameLoc, diag::err_delegating_ctor) |
| << TInfo->getTypeLoc().getLocalSourceRange(); |
| Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); |
| |
| bool InitList = true; |
| MultiExprArg Args = Init; |
| if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { |
| InitList = false; |
| Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); |
| } |
| |
| SourceRange InitRange = Init->getSourceRange(); |
| // Initialize the object. |
| InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( |
| QualType(ClassDecl->getTypeForDecl(), 0)); |
| InitializationKind Kind = |
| InitList ? InitializationKind::CreateDirectList( |
| NameLoc, Init->getLocStart(), Init->getLocEnd()) |
| : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), |
| InitRange.getEnd()); |
| InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args); |
| ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, |
| Args, nullptr); |
| if (DelegationInit.isInvalid()) |
| return true; |
| |
| assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && |
| "Delegating constructor with no target?"); |
| |
| // C++11 [class.base.init]p7: |
| // The initialization of each base and member constitutes a |
| // full-expression. |
| DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), |
| InitRange.getBegin()); |
| if (DelegationInit.isInvalid()) |
| return true; |
| |
| // If we are in a dependent context, template instantiation will |
| // perform this type-checking again. Just save the arguments that we |
| // received in a ParenListExpr. |
| // FIXME: This isn't quite ideal, since our ASTs don't capture all |
| // of the information that we have about the base |
| // initializer. However, deconstructing the ASTs is a dicey process, |
| // and this approach is far more likely to get the corner cases right. |
| if (CurContext->isDependentContext()) |
| DelegationInit = Init; |
| |
| return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(), |
| DelegationInit.getAs<Expr>(), |
| InitRange.getEnd()); |
| } |
| |
| MemInitResult |
| Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, |
| Expr *Init, CXXRecordDecl *ClassDecl, |
| SourceLocation EllipsisLoc) { |
| SourceLocation BaseLoc |
| = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); |
| |
| if (!BaseType->isDependentType() && !BaseType->isRecordType()) |
| return Diag(BaseLoc, diag::err_base_init_does_not_name_class) |
| << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); |
| |
| // C++ [class.base.init]p2: |
| // [...] Unless the mem-initializer-id names a nonstatic data |
| // member of the constructor's class or a direct or virtual base |
| // of that class, the mem-initializer is ill-formed. A |
| // mem-initializer-list can initialize a base class using any |
| // name that denotes that base class type. |
| bool Dependent = BaseType->isDependentType() || Init->isTypeDependent(); |
| |
| SourceRange InitRange = Init->getSourceRange(); |
| if (EllipsisLoc.isValid()) { |
| // This is a pack expansion. |
| if (!BaseType->containsUnexpandedParameterPack()) { |
| Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) |
| << SourceRange(BaseLoc, InitRange.getEnd()); |
| |
| EllipsisLoc = SourceLocation(); |
| } |
| } else { |
| // Check for any unexpanded parameter packs. |
| if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) |
| return true; |
| |
| if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) |
| return true; |
| } |
| |
| // Check for direct and virtual base classes. |
| const CXXBaseSpecifier *DirectBaseSpec = nullptr; |
| const CXXBaseSpecifier *VirtualBaseSpec = nullptr; |
| if (!Dependent) { |
| if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), |
| BaseType)) |
| return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl); |
| |
| FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, |
| VirtualBaseSpec); |
| |
| // C++ [base.class.init]p2: |
| // Unless the mem-initializer-id names a nonstatic data member of the |
| // constructor's class or a direct or virtual base of that class, the |
| // mem-initializer is ill-formed. |
| if (!DirectBaseSpec && !VirtualBaseSpec) { |
| // If the class has any dependent bases, then it's possible that |
| // one of those types will resolve to the same type as |
| // BaseType. Therefore, just treat this as a dependent base |
| // class initialization. FIXME: Should we try to check the |
| // initialization anyway? It seems odd. |
| if (ClassDecl->hasAnyDependentBases()) |
| Dependent = true; |
| else |
| return Diag(BaseLoc, diag::err_not_direct_base_or_virtual) |
| << BaseType << Context.getTypeDeclType(ClassDecl) |
| << BaseTInfo->getTypeLoc().getLocalSourceRange(); |
| } |
| } |
| |
| if (Dependent) { |
| DiscardCleanupsInEvaluationContext(); |
| |
| return new (Context) CXXCtorInitializer(Context, BaseTInfo, |
| /*IsVirtual=*/false, |
| InitRange.getBegin(), Init, |
| InitRange.getEnd(), EllipsisLoc); |
| } |
| |
| // C++ [base.class.init]p2: |
| // If a mem-initializer-id is ambiguous because it designates both |
| // a direct non-virtual base class and an inherited virtual base |
| // class, the mem-initializer is ill-formed. |
| if (DirectBaseSpec && VirtualBaseSpec) |
| return Diag(BaseLoc, diag::err_base_init_direct_and_virtual) |
| << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); |
| |
| const CXXBaseSpecifier *BaseSpec = DirectBaseSpec; |
| if (!BaseSpec) |
| BaseSpec = VirtualBaseSpec; |
| |
| // Initialize the base. |
| bool InitList = true; |
| MultiExprArg Args = Init; |
| if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { |
| InitList = false; |
| Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); |
| } |
| |
| InitializedEntity BaseEntity = |
| InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); |
| InitializationKind Kind = |
| InitList ? InitializationKind::CreateDirectList(BaseLoc) |
| : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(), |
| InitRange.getEnd()); |
| InitializationSequence InitSeq(*this, BaseEntity, Kind, Args); |
| ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr); |
| if (BaseInit.isInvalid()) |
| return true; |
| |
| // C++11 [class.base.init]p7: |
| // The initialization of each base and member constitutes a |
| // full-expression. |
| BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); |
| if (BaseInit.isInvalid()) |
| return true; |
| |
| // If we are in a dependent context, template instantiation will |
| // perform this type-checking again. Just save the arguments that we |
| // received in a ParenListExpr. |
| // FIXME: This isn't quite ideal, since our ASTs don't capture all |
| // of the information that we have about the base |
| // initializer. However, deconstructing the ASTs is a dicey process, |
| // and this approach is far more likely to get the corner cases right. |
| if (CurContext->isDependentContext()) |
| BaseInit = Init; |
| |
| return new (Context) CXXCtorInitializer(Context, BaseTInfo, |
| BaseSpec->isVirtual(), |
| InitRange.getBegin(), |
| BaseInit.getAs<Expr>(), |
| InitRange.getEnd(), EllipsisLoc); |
| } |
| |
| // Create a static_cast\<T&&>(expr). |
| static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) { |
| if (T.isNull()) T = E->getType(); |
| QualType TargetType = SemaRef.BuildReferenceType( |
| T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName()); |
| SourceLocation ExprLoc = E->getLocStart(); |
| TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo( |
| TargetType, ExprLoc); |
| |
| return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E, |
| SourceRange(ExprLoc, ExprLoc), |
| E->getSourceRange()).get(); |
| } |
| |
| /// ImplicitInitializerKind - How an implicit base or member initializer should |
| /// initialize its base or member. |
| enum ImplicitInitializerKind { |
| IIK_Default, |
| IIK_Copy, |
| IIK_Move, |
| IIK_Inherit |
| }; |
| |
| static bool |
| BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, |
| ImplicitInitializerKind ImplicitInitKind, |
| CXXBaseSpecifier *BaseSpec, |
| bool IsInheritedVirtualBase, |
| CXXCtorInitializer *&CXXBaseInit) { |
| InitializedEntity InitEntity |
| = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec, |
| IsInheritedVirtualBase); |
| |
| ExprResult BaseInit; |
| |
| switch (ImplicitInitKind) { |
| case IIK_Inherit: |
| case IIK_Default: { |
| InitializationKind InitKind |
| = InitializationKind::CreateDefault(Constructor->getLocation()); |
| InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None); |
| BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, None); |
| break; |
| } |
| |
| case IIK_Move: |
| case IIK_Copy: { |
| bool Moving = ImplicitInitKind == IIK_Move; |
| ParmVarDecl *Param = Constructor->getParamDecl(0); |
| QualType ParamType = Param->getType().getNonReferenceType(); |
| |
| Expr *CopyCtorArg = |
| DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), |
| SourceLocation(), Param, false, |
| Constructor->getLocation(), ParamType, |
| VK_LValue, nullptr); |
| |
| SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg)); |
| |
| // Cast to the base class to avoid ambiguities. |
| QualType ArgTy = |
| SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(), |
| ParamType.getQualifiers()); |
| |
| if (Moving) { |
| CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg); |
| } |
| |
| CXXCastPath BasePath; |
| BasePath.push_back(BaseSpec); |
| CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy, |
| CK_UncheckedDerivedToBase, |
| Moving ? VK_XValue : VK_LValue, |
| &BasePath).get(); |
| |
| InitializationKind InitKind |
| = InitializationKind::CreateDirect(Constructor->getLocation(), |
| SourceLocation(), SourceLocation()); |
| InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, CopyCtorArg); |
| BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, CopyCtorArg); |
| break; |
| } |
| } |
| |
| BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit); |
| if (BaseInit.isInvalid()) |
| return true; |
| |
| CXXBaseInit = |
| new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, |
| SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(), |
| SourceLocation()), |
| BaseSpec->isVirtual(), |
| SourceLocation(), |
| BaseInit.getAs<Expr>(), |
| SourceLocation(), |
| SourceLocation()); |
| |
| return false; |
| } |
| |
| static bool RefersToRValueRef(Expr *MemRef) { |
| ValueDecl *Referenced = cast<MemberExpr>(MemRef)->getMemberDecl(); |
| return Referenced->getType()->isRValueReferenceType(); |
| } |
| |
| static bool |
| BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, |
| ImplicitInitializerKind ImplicitInitKind, |
| FieldDecl *Field, IndirectFieldDecl *Indirect, |
| CXXCtorInitializer *&CXXMemberInit) { |
| if (Field->isInvalidDecl()) |
| return true; |
| |
| SourceLocation Loc = Constructor->getLocation(); |
| |
| if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) { |
| bool Moving = ImplicitInitKind == IIK_Move; |
| ParmVarDecl *Param = Constructor->getParamDecl(0); |
| QualType ParamType = Param->getType().getNonReferenceType(); |
| |
| // Suppress copying zero-width bitfields. |
| if (Field->isZeroLengthBitField(SemaRef.Context)) |
| return false; |
| |
| Expr *MemberExprBase = |
| DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(), |
| SourceLocation(), Param, false, |
| Loc, ParamType, VK_LValue, nullptr); |
| |
| SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase)); |
| |
| if (Moving) { |
| MemberExprBase = CastForMoving(SemaRef, MemberExprBase); |
| } |
| |
| // Build a reference to this field within the parameter. |
| CXXScopeSpec SS; |
| LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc, |
| Sema::LookupMemberName); |
| MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect) |
| : cast<ValueDecl>(Field), AS_public); |
| MemberLookup.resolveKind(); |
| ExprResult CtorArg |
| = SemaRef.BuildMemberReferenceExpr(MemberExprBase, |
| ParamType, Loc, |
| /*IsArrow=*/false, |
| SS, |
| /*TemplateKWLoc=*/SourceLocation(), |
| /*FirstQualifierInScope=*/nullptr, |
| MemberLookup, |
| /*TemplateArgs=*/nullptr, |
| /*S*/nullptr); |
| if (CtorArg.isInvalid()) |
| return true; |
| |
| // C++11 [class.copy]p15: |
| // - if a member m has rvalue reference type T&&, it is direct-initialized |
| // with static_cast<T&&>(x.m); |
| if (RefersToRValueRef(CtorArg.get())) { |
| CtorArg = CastForMoving(SemaRef, CtorArg.get()); |
| } |
| |
| InitializedEntity Entity = |
| Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, |
| /*Implicit*/ true) |
| : InitializedEntity::InitializeMember(Field, nullptr, |
| /*Implicit*/ true); |
| |
| // Direct-initialize to use the copy constructor. |
| InitializationKind InitKind = |
| InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation()); |
| |
| Expr *CtorArgE = CtorArg.getAs<Expr>(); |
| InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE); |
| ExprResult MemberInit = |
| InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1)); |
| MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); |
| if (MemberInit.isInvalid()) |
| return true; |
| |
| if (Indirect) |
| CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( |
| SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc); |
| else |
| CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer( |
| SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc); |
| return false; |
| } |
| |
| assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) && |
| "Unhandled implicit init kind!"); |
| |
| QualType FieldBaseElementType = |
| SemaRef.Context.getBaseElementType(Field->getType()); |
| |
| if (FieldBaseElementType->isRecordType()) { |
| InitializedEntity InitEntity = |
| Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr, |
| /*Implicit*/ true) |
| : InitializedEntity::InitializeMember(Field, nullptr, |
| /*Implicit*/ true); |
| InitializationKind InitKind = |
| InitializationKind::CreateDefault(Loc); |
| |
| InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None); |
| ExprResult MemberInit = |
| InitSeq.Perform(SemaRef, InitEntity, InitKind, None); |
| |
| MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); |
| if (MemberInit.isInvalid()) |
| return true; |
| |
| if (Indirect) |
| CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, |
| Indirect, Loc, |
| Loc, |
| MemberInit.get(), |
| Loc); |
| else |
| CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, |
| Field, Loc, Loc, |
| MemberInit.get(), |
| Loc); |
| return false; |
| } |
| |
| if (!Field->getParent()->isUnion()) { |
| if (FieldBaseElementType->isReferenceType()) { |
| SemaRef.Diag(Constructor->getLocation(), |
| diag::err_uninitialized_member_in_ctor) |
| << (int)Constructor->isImplicit() |
| << SemaRef.Context.getTagDeclType(Constructor->getParent()) |
| << 0 << Field->getDeclName(); |
| SemaRef.Diag(Field->getLocation(), diag::note_declared_at); |
| return true; |
| } |
| |
| if (FieldBaseElementType.isConstQualified()) { |
| SemaRef.Diag(Constructor->getLocation(), |
| diag::err_uninitialized_member_in_ctor) |
| << (int)Constructor->isImplicit() |
| << SemaRef.Context.getTagDeclType(Constructor->getParent()) |
| << 1 << Field->getDeclName(); |
| SemaRef.Diag(Field->getLocation(), diag::note_declared_at); |
| return true; |
| } |
| } |
| |
| if (FieldBaseElementType.hasNonTrivialObjCLifetime()) { |
| // ARC and Weak: |
| // Default-initialize Objective-C pointers to NULL. |
| CXXMemberInit |
| = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field, |
| Loc, Loc, |
| new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()), |
| Loc); |
| return false; |
| } |
| |
| // Nothing to initialize. |
| CXXMemberInit = nullptr; |
| return false; |
| } |
| |
| namespace { |
| struct BaseAndFieldInfo { |
| Sema &S; |
| CXXConstructorDecl *Ctor; |
| bool AnyErrorsInInits; |
| ImplicitInitializerKind IIK; |
| llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields; |
| SmallVector<CXXCtorInitializer*, 8> AllToInit; |
| llvm::DenseMap<TagDecl*, FieldDecl*> ActiveUnionMember; |
| |
| BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits) |
| : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) { |
| bool Generated = Ctor->isImplicit() || Ctor->isDefaulted(); |
| if (Ctor->getInheritedConstructor()) |
| IIK = IIK_Inherit; |
| else if (Generated && Ctor->isCopyConstructor()) |
| IIK = IIK_Copy; |
| else if (Generated && Ctor->isMoveConstructor()) |
| IIK = IIK_Move; |
| else |
| IIK = IIK_Default; |
| } |
| |
| bool isImplicitCopyOrMove() const { |
| switch (IIK) { |
| case IIK_Copy: |
| case IIK_Move: |
| return true; |
| |
| case IIK_Default: |
| case IIK_Inherit: |
| return false; |
| } |
| |
| llvm_unreachable("Invalid ImplicitInitializerKind!"); |
| } |
| |
| bool addFieldInitializer(CXXCtorInitializer *Init) { |
| AllToInit.push_back(Init); |
| |
| // Check whether this initializer makes the field "used". |
| if (Init->getInit()->HasSideEffects(S.Context)) |
| S.UnusedPrivateFields.remove(Init->getAnyMember()); |
| |
| return false; |
| } |
| |
| bool isInactiveUnionMember(FieldDecl *Field) { |
| RecordDecl *Record = Field->getParent(); |
| if (!Record->isUnion()) |
| return false; |
| |
| if (FieldDecl *Active = |
| ActiveUnionMember.lookup(Record->getCanonicalDecl())) |
| return Active != Field->getCanonicalDecl(); |
| |
| // In an implicit copy or move constructor, ignore any in-class initializer. |
| if (isImplicitCopyOrMove()) |
| return true; |
| |
| // If there's no explicit initialization, the field is active only if it |
| // has an in-class initializer... |
| if (Field->hasInClassInitializer()) |
| return false; |
| // ... or it's an anonymous struct or union whose class has an in-class |
| // initializer. |
| if (!Field->isAnonymousStructOrUnion()) |
| return true; |
| CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl(); |
| return !FieldRD->hasInClassInitializer(); |
| } |
| |
| /// Determine whether the given field is, or is within, a union member |
| /// that is inactive (because there was an initializer given for a different |
| /// member of the union, or because the union was not initialized at all). |
| bool isWithinInactiveUnionMember(FieldDecl *Field, |
| IndirectFieldDecl *Indirect) { |
| if (!Indirect) |
| return isInactiveUnionMember(Field); |
| |
| for (auto *C : Indirect->chain()) { |
| FieldDecl *Field = dyn_cast<FieldDecl>(C); |
| if (Field && isInactiveUnionMember(Field)) |
| return true; |
| } |
| return false; |
| } |
| }; |
| } |
| |
| /// Determine whether the given type is an incomplete or zero-lenfgth |
| /// array type. |
| static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) { |
| if (T->isIncompleteArrayType()) |
| return true; |
| |
| while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) { |
| if (!ArrayT->getSize()) |
| return true; |
| |
| T = ArrayT->getElementType(); |
| } |
| |
| return false; |
| } |
| |
| static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info, |
| FieldDecl *Field, |
| IndirectFieldDecl *Indirect = nullptr) { |
| if (Field->isInvalidDecl()) |
| return false; |
| |
| // Overwhelmingly common case: we have a direct initializer for this field. |
| if (CXXCtorInitializer *Init = |
| Info.AllBaseFields.lookup(Field->getCanonicalDecl())) |
| return Info.addFieldInitializer(Init); |
| |
| // C++11 [class.base.init]p8: |
| // if the entity is a non-static data member that has a |
| // brace-or-equal-initializer and either |
| // -- the constructor's class is a union and no other variant member of that |
| // union is designated by a mem-initializer-id or |
| // -- the constructor's class is not a union, and, if the entity is a member |
| // of an anonymous union, no other member of that union is designated by |
| // a mem-initializer-id, |
| // the entity is initialized as specified in [dcl.init]. |
| // |
| // We also apply the same rules to handle anonymous structs within anonymous |
| // unions. |
| if (Info.isWithinInactiveUnionMember(Field, Indirect)) |
| return false; |
| |
| if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) { |
| ExprResult DIE = |
| SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field); |
| if (DIE.isInvalid()) |
| return true; |
| |
| auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true); |
| SemaRef.checkInitializerLifetime(Entity, DIE.get()); |
| |
| CXXCtorInitializer *Init; |
| if (Indirect) |
| Init = new (SemaRef.Context) |
| CXXCtorInitializer(SemaRef.Context, Indirect, SourceLocation(), |
| SourceLocation(), DIE.get(), SourceLocation()); |
| else |
| Init = new (SemaRef.Context) |
| CXXCtorInitializer(SemaRef.Context, Field, SourceLocation(), |
| SourceLocation(), DIE.get(), SourceLocation()); |
| return Info.addFieldInitializer(Init); |
| } |
| |
| // Don't initialize incomplete or zero-length arrays. |
| if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType())) |
| return false; |
| |
| // Don't try to build an implicit initializer if there were semantic |
| // errors in any of the initializers (and therefore we might be |
| // missing some that the user actually wrote). |
| if (Info.AnyErrorsInInits) |
| return false; |
| |
| CXXCtorInitializer *Init = nullptr; |
| if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field, |
| Indirect, Init)) |
| return true; |
| |
| if (!Init) |
| return false; |
| |
| return Info.addFieldInitializer(Init); |
| } |
| |
| bool |
| Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor, |
| CXXCtorInitializer *Initializer) { |
| assert(Initializer->isDelegatingInitializer()); |
| Constructor->setNumCtorInitializers(1); |
| CXXCtorInitializer **initializer = |
| new (Context) CXXCtorInitializer*[1]; |
| memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*)); |
| Constructor->setCtorInitializers(initializer); |
| |
| if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) { |
| MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor); |
| DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation()); |
| } |
| |
| DelegatingCtorDecls.push_back(Constructor); |
| |
| DiagnoseUninitializedFields(*this, Constructor); |
| |
| return false; |
| } |
| |
| bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors, |
| ArrayRef<CXXCtorInitializer *> Initializers) { |
| if (Constructor->isDependentContext()) { |
| // Just store the initializers as written, they will be checked during |
| // instantiation. |
| if (!Initializers.empty()) { |
| Constructor->setNumCtorInitializers(Initializers.size()); |
| CXXCtorInitializer **baseOrMemberInitializers = |
| new (Context) CXXCtorInitializer*[Initializers.size()]; |
| memcpy(baseOrMemberInitializers, Initializers.data(), |
| Initializers.size() * sizeof(CXXCtorInitializer*)); |
| Constructor->setCtorInitializers(baseOrMemberInitializers); |
| } |
| |
| // Let template instantiation know whether we had errors. |
| if (AnyErrors) |
| Constructor->setInvalidDecl(); |
| |
| return false; |
| } |
| |
| BaseAndFieldInfo Info(*this, Constructor, AnyErrors); |
| |
| // We need to build the initializer AST according to order of construction |
| // and not what user specified in the Initializers list. |
| CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition(); |
| if (!ClassDecl) |
| return true; |
| |
| bool HadError = false; |
| |
| for (unsigned i = 0; i < Initializers.size(); i++) { |
| CXXCtorInitializer *Member = Initializers[i]; |
| |
| if (Member->isBaseInitializer()) |
| Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member; |
| else { |
| Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member; |
| |
| if (IndirectFieldDecl *F = Member->getIndirectMember()) { |
| for (auto *C : F->chain()) { |
| FieldDecl *FD = dyn_cast<FieldDecl>(C); |
| if (FD && FD->getParent()->isUnion()) |
| Info.ActiveUnionMember.insert(std::make_pair( |
| FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl())); |
| } |
| } else if (FieldDecl *FD = Member->getMember()) { |
| if (FD->getParent()->isUnion()) |
| Info.ActiveUnionMember.insert(std::make_pair( |
| FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl())); |
| } |
| } |
| } |
| |
| // Keep track of the direct virtual bases. |
| llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases; |
| for (auto &I : ClassDecl->bases()) { |
| if (I.isVirtual()) |
| DirectVBases.insert(&I); |
| } |
| |
| // Push virtual bases before others. |
| for (auto &VBase : ClassDecl->vbases()) { |
| if (CXXCtorInitializer *Value |
| = Info.AllBaseFields.lookup(VBase.getType()->getAs<RecordType>())) { |
| // [class.base.init]p7, per DR257: |
| // A mem-initializer where the mem-initializer-id names a virtual base |
| // class is ignored during execution of a constructor of any class that |
| // is not the most derived class. |
| if (ClassDecl->isAbstract()) { |
| // FIXME: Provide a fixit to remove the base specifier. This requires |
| // tracking the location of the associated comma for a base specifier. |
| Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored) |
| << VBase.getType() << ClassDecl; |
| DiagnoseAbstractType(ClassDecl); |
| } |
| |
| Info.AllToInit.push_back(Value); |
| } else if (!AnyErrors && !ClassDecl->isAbstract()) { |
| // [class.base.init]p8, per DR257: |
| // If a given [...] base class is not named by a mem-initializer-id |
| // [...] and the entity is not a virtual base class of an abstract |
| // class, then [...] the entity is default-initialized. |
| bool IsInheritedVirtualBase = !DirectVBases.count(&VBase); |
| CXXCtorInitializer *CXXBaseInit; |
| if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, |
| &VBase, IsInheritedVirtualBase, |
| CXXBaseInit)) { |
| HadError = true; |
| continue; |
| } |
| |
| Info.AllToInit.push_back(CXXBaseInit); |
| } |
| } |
| |
| // Non-virtual bases. |
| for (auto &Base : ClassDecl->bases()) { |
| // Virtuals are in the virtual base list and already constructed. |
| if (Base.isVirtual()) |
| continue; |
| |
| if (CXXCtorInitializer *Value |
| = Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) { |
| Info.AllToInit.push_back(Value); |
| } else if (!AnyErrors) { |
| CXXCtorInitializer *CXXBaseInit; |
| if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK, |
| &Base, /*IsInheritedVirtualBase=*/false, |
| CXXBaseInit)) { |
| HadError = true; |
| continue; |
| } |
| |
| Info.AllToInit.push_back(CXXBaseInit); |
| } |
| } |
| |
| // Fields. |
| for (auto *Mem : ClassDecl->decls()) { |
| if (auto *F = dyn_cast<FieldDecl>(Mem)) { |
| // C++ [class.bit]p2: |
| // A declaration for a bit-field that omits the identifier declares an |
| // unnamed bit-field. Unnamed bit-fields are not members and cannot be |
| // initialized. |
| if (F->isUnnamedBitfield()) |
| continue; |
| |
| // If we're not generating the implicit copy/move constructor, then we'll |
| // handle anonymous struct/union fields based on their individual |
| // indirect fields. |
| if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove()) |
| continue; |
| |
| if (CollectFieldInitializer(*this, Info, F)) |
| HadError = true; |
| continue; |
| } |
| |
| // Beyond this point, we only consider default initialization. |
| if (Info.isImplicitCopyOrMove()) |
| continue; |
| |
| if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) { |
| if (F->getType()->isIncompleteArrayType()) { |
| assert(ClassDecl->hasFlexibleArrayMember() && |
| "Incomplete array type is not valid"); |
| continue; |
| } |
| |
| // Initialize each field of an anonymous struct individually. |
| if (CollectFieldInitializer(*this, Info, F->getAnonField(), F)) |
| HadError = true; |
| |
| continue; |
| } |
| } |
| |
| unsigned NumInitializers = Info.AllToInit.size(); |
| if (NumInitializers > 0) { |
| Constructor->setNumCtorInitializers(NumInitializers); |
| CXXCtorInitializer **baseOrMemberInitializers = |
| new (Context) CXXCtorInitializer*[NumInitializers]; |
| memcpy(baseOrMemberInitializers, Info.AllToInit.data(), |
| NumInitializers * sizeof(CXXCtorInitializer*)); |
| Constructor->setCtorInitializers(baseOrMemberInitializers); |
| |
| // Constructors implicitly reference the base and member |
| // destructors. |
| MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(), |
| Constructor->getParent()); |
| } |
| |
| return HadError; |
| } |
| |
| static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) { |
| if (const RecordType *RT = Field->getType()->getAs<RecordType>()) { |
| const RecordDecl *RD = RT->getDecl(); |
| if (RD->isAnonymousStructOrUnion()) { |
| for (auto *Field : RD->fields()) |
| PopulateKeysForFields(Field, IdealInits); |
| return; |
| } |
| } |
| IdealInits.push_back(Field->getCanonicalDecl()); |
| } |
| |
| static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) { |
| return Context.getCanonicalType(BaseType).getTypePtr(); |
| } |
| |
| static const void *GetKeyForMember(ASTContext &Context, |
| CXXCtorInitializer *Member) { |
| if (!Member->isAnyMemberInitializer()) |
| return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0)); |
| |
| return Member->getAnyMember()->getCanonicalDecl(); |
| } |
| |
| static void DiagnoseBaseOrMemInitializerOrder( |
| Sema &SemaRef, const CXXConstructorDecl *Constructor, |
| ArrayRef<CXXCtorInitializer *> Inits) { |
| if (Constructor->getDeclContext()->isDependentContext()) |
| return; |
| |
| // Don't check initializers order unless the warning is enabled at the |
| // location of at least one initializer. |
| bool ShouldCheckOrder = false; |
| for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { |
| CXXCtorInitializer *Init = Inits[InitIndex]; |
| if (!SemaRef.Diags.isIgnored(diag::warn_initializer_out_of_order, |
| Init->getSourceLocation())) { |
| ShouldCheckOrder = true; |
| break; |
| } |
| } |
| if (!ShouldCheckOrder) |
| return; |
| |
| // Build the list of bases and members in the order that they'll |
| // actually be initialized. The explicit initializers should be in |
| // this same order but may be missing things. |
| SmallVector<const void*, 32> IdealInitKeys; |
| |
| const CXXRecordDecl *ClassDecl = Constructor->getParent(); |
| |
| // 1. Virtual bases. |
| for (const auto &VBase : ClassDecl->vbases()) |
| IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType())); |
| |
| // 2. Non-virtual bases. |
| for (const auto &Base : ClassDecl->bases()) { |
| if (Base.isVirtual()) |
| continue; |
| IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType())); |
| } |
| |
| // 3. Direct fields. |
| for (auto *Field : ClassDecl->fields()) { |
| if (Field->isUnnamedBitfield()) |
| continue; |
| |
| PopulateKeysForFields(Field, IdealInitKeys); |
| } |
| |
| unsigned NumIdealInits = IdealInitKeys.size(); |
| unsigned IdealIndex = 0; |
| |
| CXXCtorInitializer *PrevInit = nullptr; |
| for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) { |
| CXXCtorInitializer *Init = Inits[InitIndex]; |
| const void *InitKey = GetKeyForMember(SemaRef.Context, Init); |
| |
| // Scan forward to try to find this initializer in the idealized |
| // initializers list. |
| for (; IdealIndex != NumIdealInits; ++IdealIndex) |
| if (InitKey == IdealInitKeys[IdealIndex]) |
| break; |
| |
| // If we didn't find this initializer, it must be because we |
| // scanned past it on a previous iteration. That can only |
| // happen if we're out of order; emit a warning. |
| if (IdealIndex == NumIdealInits && PrevInit) { |
| Sema::SemaDiagnosticBuilder D = |
| SemaRef.Diag(PrevInit->getSourceLocation(), |
| diag::warn_initializer_out_of_order); |
| |
| if (PrevInit->isAnyMemberInitializer()) |
| D << 0 << PrevInit->getAnyMember()->getDeclName(); |
| else |
| D << 1 << PrevInit->getTypeSourceInfo()->getType(); |
| |
| if (Init->isAnyMemberInitializer()) |
| D << 0 << Init->getAnyMember()->getDeclName(); |
| else |
| D << 1 << Init->getTypeSourceInfo()->getType(); |
| |
| // Move back to the initializer's location in the ideal list. |
| for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex) |
| if (InitKey == IdealInitKeys[IdealIndex]) |
| break; |
| |
| assert(IdealIndex < NumIdealInits && |
| "initializer not found in initializer list"); |
| } |
| |
| PrevInit = Init; |
| } |
| } |
| |
| namespace { |
| bool CheckRedundantInit(Sema &S, |
| CXXCtorInitializer *Init, |
| CXXCtorInitializer *&PrevInit) { |
| if (!PrevInit) { |
| PrevInit = Init; |
| return false; |
| } |
| |
| if (FieldDecl *Field = Init->getAnyMember()) |
| S.Diag(Init->getSourceLocation(), |
| diag::err_multiple_mem_initialization) |
| << Field->getDeclName() |
| << Init->getSourceRange(); |
| else { |
| const Type *BaseClass = Init->getBaseClass(); |
| assert(BaseClass && "neither field nor base"); |
| S.Diag(Init->getSourceLocation(), |
| diag::err_multiple_base_initialization) |
| << QualType(BaseClass, 0) |
| << Init->getSourceRange(); |
| } |
| S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer) |
| << 0 << PrevInit->getSourceRange(); |
| |
| return true; |
| } |
| |
| typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry; |
| typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap; |
| |
| bool CheckRedundantUnionInit(Sema &S, |
| CXXCtorInitializer *Init, |
| RedundantUnionMap &Unions) { |
| FieldDecl *Field = Init->getAnyMember(); |
| RecordDecl *Parent = Field->getParent(); |
| NamedDecl *Child = Field; |
| |
| while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) { |
| if (Parent->isUnion()) { |
| UnionEntry &En = Unions[Parent]; |
| if (En.first && En.first != Child) { |
| S.Diag(Init->getSourceLocation(), |
| diag::err_multiple_mem_union_initialization) |
| << Field->getDeclName() |
| << Init->getSourceRange(); |
| S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer) |
| << 0 << En.second->getSourceRange(); |
| return true; |
| } |
| if (!En.first) { |
| En.first = Child; |
| En.second = Init; |
| } |
| if (!Parent->isAnonymousStructOrUnion()) |
| return false; |
| } |
| |
| Child = Parent; |
| Parent = cast<RecordDecl>(Parent->getDeclContext()); |
| } |
| |
| return false; |
| } |
| } |
| |
| /// ActOnMemInitializers - Handle the member initializers for a constructor. |
| void Sema::ActOnMemInitializers(Decl *ConstructorDecl, |
| SourceLocation ColonLoc, |
| ArrayRef<CXXCtorInitializer*> MemInits, |
| bool AnyErrors) { |
| if (!ConstructorDecl) |
| return; |
| |
| AdjustDeclIfTemplate(ConstructorDecl); |
| |
| CXXConstructorDecl *Constructor |
| = dyn_cast<CXXConstructorDecl>(ConstructorDecl); |
| |
| if (!Constructor) { |
| Diag(ColonLoc, diag::err_only_constructors_take_base_inits); |
| return; |
| } |
| |
| // Mapping for the duplicate initializers check. |
| // For member initializers, this is keyed with a FieldDecl*. |
| // For base initializers, this is keyed with a Type*. |
| llvm::DenseMap<const void *, CXXCtorInitializer *> Members; |
| |
| // Mapping for the inconsistent anonymous-union initializers check. |
| RedundantUnionMap MemberUnions; |
| |
| bool HadError = false; |
| for (unsigned i = 0; i < MemInits.size(); i++) { |
| CXXCtorInitializer *Init = MemInits[i]; |
| |
| // Set the source order index. |
| Init->setSourceOrder(i); |
| |
| if (Init->isAnyMemberInitializer()) { |
| const void *Key = GetKeyForMember(Context, Init); |
| if (CheckRedundantInit(*this, Init, Members[Key]) || |
| CheckRedundantUnionInit(*this, Init, MemberUnions)) |
| HadError = true; |
| } else if (Init->isBaseInitializer()) { |
| const void *Key = GetKeyForMember(Context, Init); |
| if (CheckRedundantInit(*this, Init, Members[Key])) |
| HadError = true; |
| } else { |
| assert(Init->isDelegatingInitializer()); |
| // This must be the only initializer |
| if (MemInits.size() != 1) { |
| Diag(Init->getSourceLocation(), |
| diag::err_delegating_initializer_alone) |
| << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange(); |
| // We will treat this as being the only initializer. |
| } |
| SetDelegatingInitializer(Constructor, MemInits[i]); |
| // Return immediately as the initializer is set. |
| return; |
| } |
| } |
| |
| if (HadError) |
| return; |
| |
| DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits); |
| |
| SetCtorInitializers(Constructor, AnyErrors, MemInits); |
| |
| DiagnoseUninitializedFields(*this, Constructor); |
| } |
| |
| void |
| Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location, |
| CXXRecordDecl *ClassDecl) { |
| // Ignore dependent contexts. Also ignore unions, since their members never |
| // have destructors implicitly called. |
| if (ClassDecl->isDependentContext() || ClassDecl->isUnion()) |
| return; |
| |
| // FIXME: all the access-control diagnostics are positioned on the |
| // field/base declaration. That's probably good; that said, the |
| // user might reasonably want to know why the destructor is being |
| // emitted, and we currently don't say. |
| |
| // Non-static data members. |
| for (auto *Field : ClassDecl->fields()) { |
| if (Field->isInvalidDecl()) |
| continue; |
| |
| // Don't destroy incomplete or zero-length arrays. |
| if (isIncompleteOrZeroLengthArrayType(Context, Field->getType())) |
| continue; |
| |
| QualType FieldType = Context.getBaseElementType(Field->getType()); |
| |
| const RecordType* RT = FieldType->getAs<RecordType>(); |
| if (!RT) |
| continue; |
| |
| CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); |
| if (FieldClassDecl->isInvalidDecl()) |
| continue; |
| if (FieldClassDecl->hasIrrelevantDestructor()) |
| continue; |
| // The destructor for an implicit anonymous union member is never invoked. |
| if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion()) |
| continue; |
| |
| CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl); |
| assert(Dtor && "No dtor found for FieldClassDecl!"); |
| CheckDestructorAccess(Field->getLocation(), Dtor, |
| PDiag(diag::err_access_dtor_field) |
| << Field->getDeclName() |
| << FieldType); |
| |
| MarkFunctionReferenced(Location, Dtor); |
| DiagnoseUseOfDecl(Dtor, Location); |
| } |
| |
| // We only potentially invoke the destructors of potentially constructed |
| // subobjects. |
| bool VisitVirtualBases = !ClassDecl->isAbstract(); |
| |
| llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases; |
| |
| // Bases. |
| for (const auto &Base : ClassDecl->bases()) { |
| // Bases are always records in a well-formed non-dependent class. |
| const RecordType *RT = Base.getType()->getAs<RecordType>(); |
| |
| // Remember direct virtual bases. |
| if (Base.isVirtual()) { |
| if (!VisitVirtualBases) |
| continue; |
| DirectVirtualBases.insert(RT); |
| } |
| |
| CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); |
| // If our base class is invalid, we probably can't get its dtor anyway. |
| if (BaseClassDecl->isInvalidDecl()) |
| continue; |
| if (BaseClassDecl->hasIrrelevantDestructor()) |
| continue; |
| |
| CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); |
| assert(Dtor && "No dtor found for BaseClassDecl!"); |
| |
| // FIXME: caret should be on the start of the class name |
| CheckDestructorAccess(Base.getLocStart(), Dtor, |
| PDiag(diag::err_access_dtor_base) |
| << Base.getType() |
| << Base.getSourceRange(), |
| Context.getTypeDeclType(ClassDecl)); |
| |
| MarkFunctionReferenced(Location, Dtor); |
| DiagnoseUseOfDecl(Dtor, Location); |
| } |
| |
| if (!VisitVirtualBases) |
| return; |
| |
| // Virtual bases. |
| for (const auto &VBase : ClassDecl->vbases()) { |
| // Bases are always records in a well-formed non-dependent class. |
| const RecordType *RT = VBase.getType()->castAs<RecordType>(); |
| |
| // Ignore direct virtual bases. |
| if (DirectVirtualBases.count(RT)) |
| continue; |
| |
| CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); |
| // If our base class is invalid, we probably can't get its dtor anyway. |
| if (BaseClassDecl->isInvalidDecl()) |
| continue; |
| if (BaseClassDecl->hasIrrelevantDestructor()) |
| continue; |
| |
| CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl); |
| assert(Dtor && "No dtor found for BaseClassDecl!"); |
| if (CheckDestructorAccess( |
| ClassDecl->getLocation(), Dtor, |
| PDiag(diag::err_access_dtor_vbase) |
| << Context.getTypeDeclType(ClassDecl) << VBase.getType(), |
| Context.getTypeDeclType(ClassDecl)) == |
| AR_accessible) { |
| CheckDerivedToBaseConversion( |
| Context.getTypeDeclType(ClassDecl), VBase.getType(), |
| diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(), |
| SourceRange(), DeclarationName(), nullptr); |
| } |
| |
| MarkFunctionReferenced(Location, Dtor); |
| DiagnoseUseOfDecl(Dtor, Location); |
| } |
| } |
| |
| void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) { |
| if (!CDtorDecl) |
| return; |
| |
| if (CXXConstructorDecl *Constructor |
| = dyn_cast<CXXConstructorDecl>(CDtorDecl)) { |
| SetCtorInitializers(Constructor, /*AnyErrors=*/false); |
| DiagnoseUninitializedFields(*this, Constructor); |
| } |
| } |
| |
| bool Sema::isAbstractType(SourceLocation Loc, QualType T) { |
| if (!getLangOpts().CPlusPlus) |
| return false; |
| |
| const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl(); |
| if (!RD) |
| return false; |
| |
| // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a |
| // class template specialization here, but doing so breaks a lot of code. |
| |
| // We can't answer whether something is abstract until it has a |
| // definition. If it's currently being defined, we'll walk back |
| // over all the declarations when we have a full definition. |
| const CXXRecordDecl *Def = RD->getDefinition(); |
| if (!Def || Def->isBeingDefined()) |
| return false; |
| |
| return RD->isAbstract(); |
| } |
| |
| bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T, |
| TypeDiagnoser &Diagnoser) { |
| if (!isAbstractType(Loc, T)) |
| return false; |
| |
| T = Context.getBaseElementType(T); |
| Diagnoser.diagnose(*this, Loc, T); |
| DiagnoseAbstractType(T->getAsCXXRecordDecl()); |
| return true; |
| } |
| |
| void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) { |
| // Check if we've already emitted the list of pure virtual functions |
| // for this class. |
| if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD)) |
| return; |
| |
| // If the diagnostic is suppressed, don't emit the notes. We're only |
| // going to emit them once, so try to attach them to a diagnostic we're |
| // actually going to show. |
| if (Diags.isLastDiagnosticIgnored()) |
| return; |
| |
| CXXFinalOverriderMap FinalOverriders; |
| RD->getFinalOverriders(FinalOverriders); |
| |
| // Keep a set of seen pure methods so we won't diagnose the same method |
| // more than once. |
| llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods; |
| |
| for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(), |
| MEnd = FinalOverriders.end(); |
| M != MEnd; |
| ++M) { |
| for (OverridingMethods::iterator SO = M->second.begin(), |
| SOEnd = M->second.end(); |
| SO != SOEnd; ++SO) { |
| // C++ [class.abstract]p4: |
| // A class is abstract if it contains or inherits at least one |
| // pure virtual function for which the final overrider is pure |
| // virtual. |
| |
| // |
| if (SO->second.size() != 1) |
| continue; |
| |
| if (!SO->second.front().Method->isPure()) |
| continue; |
| |
| if (!SeenPureMethods.insert(SO->second.front().Method).second) |
| continue; |
| |
| Diag(SO->second.front().Method->getLocation(), |
| diag::note_pure_virtual_function) |
| << SO->second.front().Method->getDeclName() << RD->getDeclName(); |
| } |
| } |
| |
| if (!PureVirtualClassDiagSet) |
| PureVirtualClassDiagSet.reset(new RecordDeclSetTy); |
| PureVirtualClassDiagSet->insert(RD); |
| } |
| |
| namespace { |
| struct AbstractUsageInfo { |
| Sema &S; |
| CXXRecordDecl *Record; |
| CanQualType AbstractType; |
| bool Invalid; |
| |
| AbstractUsageInfo(Sema &S, CXXRecordDecl *Record) |
| : S(S), Record(Record), |
| AbstractType(S.Context.getCanonicalType( |
| S.Context.getTypeDeclType(Record))), |
| Invalid(false) {} |
| |
| void DiagnoseAbstractType() { |
| if (Invalid) return; |
| S.DiagnoseAbstractType(Record); |
| Invalid = true; |
| } |
| |
| void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel); |
| }; |
| |
| struct CheckAbstractUsage { |
| AbstractUsageInfo &Info; |
| const NamedDecl *Ctx; |
| |
| CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx) |
| : Info(Info), Ctx(Ctx) {} |
| |
| void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) { |
| switch (TL.getTypeLocClass()) { |
| #define ABSTRACT_TYPELOC(CLASS, PARENT) |
| #define TYPELOC(CLASS, PARENT) \ |
| case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break; |
| #include "clang/AST/TypeLocNodes.def" |
| } |
| } |
| |
| void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) { |
| Visit(TL.getReturnLoc(), Sema::AbstractReturnType); |
| for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) { |
| if (!TL.getParam(I)) |
| continue; |
| |
| TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo(); |
| if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType); |
| } |
| } |
| |
| void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) { |
| Visit(TL.getElementLoc(), Sema::AbstractArrayType); |
| } |
| |
| void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) { |
| // Visit the type parameters from a permissive context. |
| for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { |
| TemplateArgumentLoc TAL = TL.getArgLoc(I); |
| if (TAL.getArgument().getKind() == TemplateArgument::Type) |
| if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo()) |
| Visit(TSI->getTypeLoc(), Sema::AbstractNone); |
| // TODO: other template argument types? |
| } |
| } |
| |
| // Visit pointee types from a permissive context. |
| #define CheckPolymorphic(Type) \ |
| void Check(Type TL, Sema::AbstractDiagSelID Sel) { \ |
| Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \ |
| } |
| CheckPolymorphic(PointerTypeLoc) |
| CheckPolymorphic(ReferenceTypeLoc) |
| CheckPolymorphic(MemberPointerTypeLoc) |
| CheckPolymorphic(BlockPointerTypeLoc) |
| CheckPolymorphic(AtomicTypeLoc) |
| |
| /// Handle all the types we haven't given a more specific |
| /// implementation for above. |
| void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) { |
| // Every other kind of type that we haven't called out already |
| // that has an inner type is either (1) sugar or (2) contains that |
| // inner type in some way as a subobject. |
| if (TypeLoc Next = TL.getNextTypeLoc()) |
| return Visit(Next, Sel); |
| |
| // If there's no inner type and we're in a permissive context, |
| // don't diagnose. |
| if (Sel == Sema::AbstractNone) return; |
| |
| // Check whether the type matches the abstract type. |
| QualType T = TL.getType(); |
| if (T->isArrayType()) { |
| Sel = Sema::AbstractArrayType; |
| T = Info.S.Context.getBaseElementType(T); |
| } |
| CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType(); |
| if (CT != Info.AbstractType) return; |
| |
| // It matched; do some magic. |
| if (Sel == Sema::AbstractArrayType) { |
| Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type) |
| << T << TL.getSourceRange(); |
| } else { |
| Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl) |
| << Sel << T << TL.getSourceRange(); |
| } |
| Info.DiagnoseAbstractType(); |
| } |
| }; |
| |
| void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL, |
| Sema::AbstractDiagSelID Sel) { |
| CheckAbstractUsage(*this, D).Visit(TL, Sel); |
| } |
| |
| } |
| |
| /// Check for invalid uses of an abstract type in a method declaration. |
| static void CheckAbstractClassUsage(AbstractUsageInfo &Info, |
| CXXMethodDecl *MD) { |
| // No need to do the check on definitions, which require that |
| // the return/param types be complete. |
| if (MD->doesThisDeclarationHaveABody()) |
| return; |
| |
| // For safety's sake, just ignore it if we don't have type source |
| // information. This should never happen for non-implicit methods, |
| // but... |
| if (TypeSourceInfo *TSI = MD->getTypeSourceInfo()) |
| Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone); |
| } |
| |
| /// Check for invalid uses of an abstract type within a class definition. |
| static void CheckAbstractClassUsage(AbstractUsageInfo &Info, |
| CXXRecordDecl *RD) { |
| for (auto *D : RD->decls()) { |
| if (D->isImplicit()) continue; |
| |
| // Methods and method templates. |
| if (isa<CXXMethodDecl>(D)) { |
| CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D)); |
| } else if (isa<FunctionTemplateDecl>(D)) { |
| FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl(); |
| CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD)); |
| |
| // Fields and static variables. |
| } else if (isa<FieldDecl>(D)) { |
| FieldDecl *FD = cast<FieldDecl>(D); |
| if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) |
| Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType); |
| } else if (isa<VarDecl>(D)) { |
| VarDecl *VD = cast<VarDecl>(D); |
| if (TypeSourceInfo *TSI = VD->getTypeSourceInfo()) |
| Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType); |
| |
| // Nested classes and class templates. |
| } else if (isa<CXXRecordDecl>(D)) { |
| CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D)); |
| } else if (isa<ClassTemplateDecl>(D)) { |
| CheckAbstractClassUsage(Info, |
| cast<ClassTemplateDecl>(D)->getTemplatedDecl()); |
| } |
| } |
| } |
| |
| static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) { |
| Attr *ClassAttr = getDLLAttr(Class); |
| if (!ClassAttr) |
| return; |
| |
| assert(ClassAttr->getKind() == attr::DLLExport); |
| |
| TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); |
| |
| if (TSK == TSK_ExplicitInstantiationDeclaration) |
| // Don't go any further if this is just an explicit instantiation |
| // declaration. |
| return; |
| |
| for (Decl *Member : Class->decls()) { |
| // Defined static variables that are members of an exported base |
| // class must be marked export too. |
| auto *VD = dyn_cast<VarDecl>(Member); |
| if (VD && Member->getAttr<DLLExportAttr>() && |
| VD->getStorageClass() == SC_Static && |
| TSK == TSK_ImplicitInstantiation) |
| S.MarkVariableReferenced(VD->getLocation(), VD); |
| |
| auto *MD = dyn_cast<CXXMethodDecl>(Member); |
| if (!MD) |
| continue; |
| |
| if (Member->getAttr<DLLExportAttr>()) { |
| if (MD->isUserProvided()) { |
| // Instantiate non-default class member functions ... |
| |
| // .. except for certain kinds of template specializations. |
| if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited()) |
| continue; |
| |
| S.MarkFunctionReferenced(Class->getLocation(), MD); |
| |
| // The function will be passed to the consumer when its definition is |
| // encountered. |
| } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || |
| MD->isCopyAssignmentOperator() || |
| MD->isMoveAssignmentOperator()) { |
| // Synthesize and instantiate non-trivial implicit methods, explicitly |
| // defaulted methods, and the copy and move assignment operators. The |
| // latter are exported even if they are trivial, because the address of |
| // an operator can be taken and should compare equal across libraries. |
| DiagnosticErrorTrap Trap(S.Diags); |
| S.MarkFunctionReferenced(Class->getLocation(), MD); |
| if (Trap.hasErrorOccurred()) { |
| S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class) |
| << Class << !S.getLangOpts().CPlusPlus11; |
| break; |
| } |
| |
| // There is no later point when we will see the definition of this |
| // function, so pass it to the consumer now. |
| S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); |
| } |
| } |
| } |
| } |
| |
| static void checkForMultipleExportedDefaultConstructors(Sema &S, |
| CXXRecordDecl *Class) { |
| // Only the MS ABI has default constructor closures, so we don't need to do |
| // this semantic checking anywhere else. |
| if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft()) |
| return; |
| |
| CXXConstructorDecl *LastExportedDefaultCtor = nullptr; |
| for (Decl *Member : Class->decls()) { |
| // Look for exported default constructors. |
| auto *CD = dyn_cast<CXXConstructorDecl>(Member); |
| if (!CD || !CD->isDefaultConstructor()) |
| continue; |
| auto *Attr = CD->getAttr<DLLExportAttr>(); |
| if (!Attr) |
| continue; |
| |
| // If the class is non-dependent, mark the default arguments as ODR-used so |
| // that we can properly codegen the constructor closure. |
| if (!Class->isDependentContext()) { |
| for (ParmVarDecl *PD : CD->parameters()) { |
| (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD); |
| S.DiscardCleanupsInEvaluationContext(); |
| } |
| } |
| |
| if (LastExportedDefaultCtor) { |
| S.Diag(LastExportedDefaultCtor->getLocation(), |
| diag::err_attribute_dll_ambiguous_default_ctor) |
| << Class; |
| S.Diag(CD->getLocation(), diag::note_entity_declared_at) |
| << CD->getDeclName(); |
| return; |
| } |
| LastExportedDefaultCtor = CD; |
| } |
| } |
| |
| void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) { |
| // Mark any compiler-generated routines with the implicit code_seg attribute. |
| for (auto *Method : Class->methods()) { |
| if (Method->isUserProvided()) |
| continue; |
| if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true)) |
| Method->addAttr(A); |
| } |
| } |
| |
| /// Check class-level dllimport/dllexport attribute. |
| void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) { |
| Attr *ClassAttr = getDLLAttr(Class); |
| |
| // MSVC inherits DLL attributes to partial class template specializations. |
| if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) { |
| if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) { |
| if (Attr *TemplateAttr = |
| getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { |
| auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext())); |
| A->setInherited(true); |
| ClassAttr = A; |
| } |
| } |
| } |
| |
| if (!ClassAttr) |
| return; |
| |
| if (!Class->isExternallyVisible()) { |
| Diag(Class->getLocation(), diag::err_attribute_dll_not_extern) |
| << Class << ClassAttr; |
| return; |
| } |
| |
| if (Context.getTargetInfo().getCXXABI().isMicrosoft() && |
| !ClassAttr->isInherited()) { |
| // Diagnose dll attributes on members of class with dll attribute. |
| for (Decl *Member : Class->decls()) { |
| if (!isa<VarDecl>(Member) && !isa<CXXMethodDecl>(Member)) |
| continue; |
| InheritableAttr *MemberAttr = getDLLAttr(Member); |
| if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl()) |
| continue; |
| |
| Diag(MemberAttr->getLocation(), |
| diag::err_attribute_dll_member_of_dll_class) |
| << MemberAttr << ClassAttr; |
| Diag(ClassAttr->getLocation(), diag::note_previous_attribute); |
| Member->setInvalidDecl(); |
| } |
| } |
| |
| if (Class->getDescribedClassTemplate()) |
| // Don't inherit dll attribute until the template is instantiated. |
| return; |
| |
| // The class is either imported or exported. |
| const bool ClassExported = ClassAttr->getKind() == attr::DLLExport; |
| |
| // Check if this was a dllimport attribute propagated from a derived class to |
| // a base class template specialization. We don't apply these attributes to |
| // static data members. |
| const bool PropagatedImport = |
| !ClassExported && |
| cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate(); |
| |
| TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind(); |
| |
| // Ignore explicit dllexport on explicit class template instantiation declarations. |
| if (ClassExported && !ClassAttr->isInherited() && |
| TSK == TSK_ExplicitInstantiationDeclaration) { |
| Class->dropAttr<DLLExportAttr>(); |
| return; |
| } |
| |
| // Force declaration of implicit members so they can inherit the attribute. |
| ForceDeclarationOfImplicitMembers(Class); |
| |
| // FIXME: MSVC's docs say all bases must be exportable, but this doesn't |
| // seem to be true in practice? |
| |
| for (Decl *Member : Class->decls()) { |
| VarDecl *VD = dyn_cast<VarDecl>(Member); |
| CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); |
| |
| // Only methods and static fields inherit the attributes. |
| if (!VD && !MD) |
| continue; |
| |
| if (MD) { |
| // Don't process deleted methods. |
| if (MD->isDeleted()) |
| continue; |
| |
| if (MD->isInlined()) { |
| // MinGW does not import or export inline methods. |
| if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && |
| !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) |
| continue; |
| |
| // MSVC versions before 2015 don't export the move assignment operators |
| // and move constructor, so don't attempt to import/export them if |
| // we have a definition. |
| auto *Ctor = dyn_cast<CXXConstructorDecl>(MD); |
| if ((MD->isMoveAssignmentOperator() || |
| (Ctor && Ctor->isMoveConstructor())) && |
| !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015)) |
| continue; |
| |
| // MSVC2015 doesn't export trivial defaulted x-tor but copy assign |
| // operator is exported anyway. |
| if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && |
| (Ctor || isa<CXXDestructorDecl>(MD)) && MD->isTrivial()) |
| continue; |
| } |
| } |
| |
| // Don't apply dllimport attributes to static data members of class template |
| // instantiations when the attribute is propagated from a derived class. |
| if (VD && PropagatedImport) |
| continue; |
| |
| if (!cast<NamedDecl>(Member)->isExternallyVisible()) |
| continue; |
| |
| if (!getDLLAttr(Member)) { |
| auto *NewAttr = |
| cast<InheritableAttr>(ClassAttr->clone(getASTContext())); |
| NewAttr->setInherited(true); |
| Member->addAttr(NewAttr); |
| |
| if (MD) { |
| // Propagate DLLAttr to friend re-declarations of MD that have already |
| // been constructed. |
| for (FunctionDecl *FD = MD->getMostRecentDecl(); FD; |
| FD = FD->getPreviousDecl()) { |
| if (FD->getFriendObjectKind() == Decl::FOK_None) |
| continue; |
| assert(!getDLLAttr(FD) && |
| "friend re-decl should not already have a DLLAttr"); |
| NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext())); |
| NewAttr->setInherited(true); |
| FD->addAttr(NewAttr); |
| } |
| } |
| } |
| } |
| |
| if (ClassExported) |
| DelayedDllExportClasses.push_back(Class); |
| } |
| |
| /// Perform propagation of DLL attributes from a derived class to a |
| /// templated base class for MS compatibility. |
| void Sema::propagateDLLAttrToBaseClassTemplate( |
| CXXRecordDecl *Class, Attr *ClassAttr, |
| ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) { |
| if (getDLLAttr( |
| BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) { |
| // If the base class template has a DLL attribute, don't try to change it. |
| return; |
| } |
| |
| auto TSK = BaseTemplateSpec->getSpecializationKind(); |
| if (!getDLLAttr(BaseTemplateSpec) && |
| (TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration || |
| TSK == TSK_ImplicitInstantiation)) { |
| // The template hasn't been instantiated yet (or it has, but only as an |
| // explicit instantiation declaration or implicit instantiation, which means |
| // we haven't codegenned any members yet), so propagate the attribute. |
| auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext())); |
| NewAttr->setInherited(true); |
| BaseTemplateSpec->addAttr(NewAttr); |
| |
| // If this was an import, mark that we propagated it from a derived class to |
| // a base class template specialization. |
| if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr)) |
| ImportAttr->setPropagatedToBaseTemplate(); |
| |
| // If the template is already instantiated, checkDLLAttributeRedeclaration() |
| // needs to be run again to work see the new attribute. Otherwise this will |
| // get run whenever the template is instantiated. |
| if (TSK != TSK_Undeclared) |
| checkClassLevelDLLAttribute(BaseTemplateSpec); |
| |
| return; |
| } |
| |
| if (getDLLAttr(BaseTemplateSpec)) { |
| // The template has already been specialized or instantiated with an |
| // attribute, explicitly or through propagation. We should not try to change |
| // it. |
| return; |
| } |
| |
| // The template was previously instantiated or explicitly specialized without |
| // a dll attribute, It's too late for us to add an attribute, so warn that |
| // this is unsupported. |
| Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class) |
| << BaseTemplateSpec->isExplicitSpecialization(); |
| Diag(ClassAttr->getLocation(), diag::note_attribute); |
| if (BaseTemplateSpec->isExplicitSpecialization()) { |
| Diag(BaseTemplateSpec->getLocation(), |
| diag::note_template_class_explicit_specialization_was_here) |
| << BaseTemplateSpec; |
| } else { |
| Diag(BaseTemplateSpec->getPointOfInstantiation(), |
| diag::note_template_class_instantiation_was_here) |
| << BaseTemplateSpec; |
| } |
| } |
| |
| static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD, |
| SourceLocation DefaultLoc) { |
| switch (S.getSpecialMember(MD)) { |
| case Sema::CXXDefaultConstructor: |
| S.DefineImplicitDefaultConstructor(DefaultLoc, |
| cast<CXXConstructorDecl>(MD)); |
| break; |
| case Sema::CXXCopyConstructor: |
| S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); |
| break; |
| case Sema::CXXCopyAssignment: |
| S.DefineImplicitCopyAssignment(DefaultLoc, MD); |
| break; |
| case Sema::CXXDestructor: |
| S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD)); |
| break; |
| case Sema::CXXMoveConstructor: |
| S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD)); |
| break; |
| case Sema::CXXMoveAssignment: |
| S.DefineImplicitMoveAssignment(DefaultLoc, MD); |
| break; |
| case Sema::CXXInvalid: |
| llvm_unreachable("Invalid special member."); |
| } |
| } |
| |
| /// Determine whether a type is permitted to be passed or returned in |
| /// registers, per C++ [class.temporary]p3. |
| static bool canPassInRegisters(Sema &S, CXXRecordDecl *D, |
| TargetInfo::CallingConvKind CCK) { |
| if (D->isDependentType() || D->isInvalidDecl()) |
| return false; |
| |
| // Clang <= 4 used the pre-C++11 rule, which ignores move operations. |
| // The PS4 platform ABI follows the behavior of Clang 3.2. |
| if (CCK == TargetInfo::CCK_ClangABI4OrPS4) |
| return !D->hasNonTrivialDestructorForCall() && |
| !D->hasNonTrivialCopyConstructorForCall(); |
| |
| if (CCK == TargetInfo::CCK_MicrosoftWin64) { |
| bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false; |
| bool DtorIsTrivialForCall = false; |
| |
| // If a class has at least one non-deleted, trivial copy constructor, it |
| // is passed according to the C ABI. Otherwise, it is passed indirectly. |
| // |
| // Note: This permits classes with non-trivial copy or move ctors to be |
| // passed in registers, so long as they *also* have a trivial copy ctor, |
| // which is non-conforming. |
| if (D->needsImplicitCopyConstructor()) { |
| if (!D->defaultedCopyConstructorIsDeleted()) { |
| if (D->hasTrivialCopyConstructor()) |
| CopyCtorIsTrivial = true; |
| if (D->hasTrivialCopyConstructorForCall()) |
| CopyCtorIsTrivialForCall = true; |
| } |
| } else { |
| for (const CXXConstructorDecl *CD : D->ctors()) { |
| if (CD->isCopyConstructor() && !CD->isDeleted()) { |
| if (CD->isTrivial()) |
| CopyCtorIsTrivial = true; |
| if (CD->isTrivialForCall()) |
| CopyCtorIsTrivialForCall = true; |
| } |
| } |
| } |
| |
| if (D->needsImplicitDestructor()) { |
| if (!D->defaultedDestructorIsDeleted() && |
| D->hasTrivialDestructorForCall()) |
| DtorIsTrivialForCall = true; |
| } else if (const auto *DD = D->getDestructor()) { |
| if (!DD->isDeleted() && DD->isTrivialForCall()) |
| DtorIsTrivialForCall = true; |
| } |
| |
| // If the copy ctor and dtor are both trivial-for-calls, pass direct. |
| if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall) |
| return true; |
| |
| // If a class has a destructor, we'd really like to pass it indirectly |
| // because it allows us to elide copies. Unfortunately, MSVC makes that |
| // impossible for small types, which it will pass in a single register or |
| // stack slot. Most objects with dtors are large-ish, so handle that early. |
| // We can't call out all large objects as being indirect because there are |
| // multiple x64 calling conventions and the C++ ABI code shouldn't dictate |
| // how we pass large POD types. |
| |
| // Note: This permits small classes with nontrivial destructors to be |
| // passed in registers, which is non-conforming. |
| if (CopyCtorIsTrivial && |
| S.getASTContext().getTypeSize(D->getTypeForDecl()) <= 64) |
| return true; |
| return false; |
| } |
| |
| // Per C++ [class.temporary]p3, the relevant condition is: |
| // each copy constructor, move constructor, and destructor of X is |
| // either trivial or deleted, and X has at least one non-deleted copy |
| // or move constructor |
| bool HasNonDeletedCopyOrMove = false; |
| |
| if (D->needsImplicitCopyConstructor() && |
| !D->defaultedCopyConstructorIsDeleted()) { |
| if (!D->hasTrivialCopyConstructorForCall()) |
| return false; |
| HasNonDeletedCopyOrMove = true; |
| } |
| |
| if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() && |
| !D->defaultedMoveConstructorIsDeleted()) { |
| if (!D->hasTrivialMoveConstructorForCall()) |
| return false; |
| HasNonDeletedCopyOrMove = true; |
| } |
| |
| if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() && |
| !D->hasTrivialDestructorForCall()) |
| return false; |
| |
| for (const CXXMethodDecl *MD : D->methods()) { |
| if (MD->isDeleted()) |
| continue; |
| |
| auto *CD = dyn_cast<CXXConstructorDecl>(MD); |
| if (CD && CD->isCopyOrMoveConstructor()) |
| HasNonDeletedCopyOrMove = true; |
| else if (!isa<CXXDestructorDecl>(MD)) |
| continue; |
| |
| if (!MD->isTrivialForCall()) |
| return false; |
| } |
| |
| return HasNonDeletedCopyOrMove; |
| } |
| |
| /// Perform semantic checks on a class definition that has been |
| /// completing, introducing implicitly-declared members, checking for |
| /// abstract types, etc. |
| void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { |
| if (!Record) |
| return; |
| |
| if (Record->isAbstract() && !Record->isInvalidDecl()) { |
| AbstractUsageInfo Info(*this, Record); |
| CheckAbstractClassUsage(Info, Record); |
| } |
| |
| // If this is not an aggregate type and has no user-declared constructor, |
| // complain about any non-static data members of reference or const scalar |
| // type, since they will never get initializers. |
| if (!Record->isInvalidDecl() && !Record->isDependentType() && |
| !Record->isAggregate() && !Record->hasUserDeclaredConstructor() && |
| !Record->isLambda()) { |
| bool Complained = false; |
| for (const auto *F : Record->fields()) { |
| if (F->hasInClassInitializer() || F->isUnnamedBitfield()) |
| continue; |
| |
| if (F->getType()->isReferenceType() || |
| (F->getType().isConstQualified() && F->getType()->isScalarType())) { |
| if (!Complained) { |
| Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst) |
| << Record->getTagKind() << Record; |
| Complained = true; |
| } |
| |
| Diag(F->getLocation(), diag::note_refconst_member_not_initialized) |
| << F->getType()->isReferenceType() |
| << F->getDeclName(); |
| } |
| } |
| } |
| |
| if (Record->getIdentifier()) { |
| // C++ [class.mem]p13: |
| // If T is the name of a class, then each of the following shall have a |
| // name different from T: |
| // - every member of every anonymous union that is a member of class T. |
| // |
| // C++ [class.mem]p14: |
| // In addition, if class T has a user-declared constructor (12.1), every |
| // non-static data member of class T shall have a name different from T. |
| DeclContext::lookup_result R = Record->lookup(Record->getDeclName()); |
| for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; |
| ++I) { |
| NamedDecl *D = (*I)->getUnderlyingDecl(); |
| if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) && |
| Record->hasUserDeclaredConstructor()) || |
| isa<IndirectFieldDecl>(D)) { |
| Diag((*I)->getLocation(), diag::err_member_name_of_class) |
| << D->getDeclName(); |
| break; |
| } |
| } |
| } |
| |
| // Warn if the class has virtual methods but non-virtual public destructor. |
| if (Record->isPolymorphic() && !Record->isDependentType()) { |
| CXXDestructorDecl *dtor = Record->getDestructor(); |
| if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) && |
| !Record->hasAttr<FinalAttr>()) |
| Diag(dtor ? dtor->getLocation() : Record->getLocation(), |
| diag::warn_non_virtual_dtor) << Context.getRecordType(Record); |
| } |
| |
| if (Record->isAbstract()) { |
| if (FinalAttr *FA = Record->getAttr<FinalAttr>()) { |
| Diag(Record->getLocation(), diag::warn_abstract_final_class) |
| << FA->isSpelledAsSealed(); |
| DiagnoseAbstractType(Record); |
| } |
| } |
| |
| // See if trivial_abi has to be dropped. |
| if (Record->hasAttr<TrivialABIAttr>()) |
| checkIllFormedTrivialABIStruct(*Record); |
| |
| // Set HasTrivialSpecialMemberForCall if the record has attribute |
| // "trivial_abi". |
| bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>(); |
| |
| if (HasTrivialABI) |
| Record->setHasTrivialSpecialMemberForCall(); |
| |
| bool HasMethodWithOverrideControl = false, |
| HasOverridingMethodWithoutOverrideControl = false; |
| if (!Record->isDependentType()) { |
| for (auto *M : Record->methods()) { |
| // See if a method overloads virtual methods in a base |
| // class without overriding any. |
| if (!M->isStatic()) |
| DiagnoseHiddenVirtualMethods(M); |
| if (M->hasAttr<OverrideAttr>()) |
| HasMethodWithOverrideControl = true; |
| else if (M->size_overridden_methods() > 0) |
| HasOverridingMethodWithoutOverrideControl = true; |
| // Check whether the explicitly-defaulted special members are valid. |
| if (!M->isInvalidDecl() && M->isExplicitlyDefaulted()) |
| CheckExplicitlyDefaultedSpecialMember(M); |
| |
| // For an explicitly defaulted or deleted special member, we defer |
| // determining triviality until the class is complete. That time is now! |
| CXXSpecialMember CSM = getSpecialMember(M); |
| if (!M->isImplicit() && !M->isUserProvided()) { |
| if (CSM != CXXInvalid) { |
| M->setTrivial(SpecialMemberIsTrivial(M, CSM)); |
| // Inform the class that we've finished declaring this member. |
| Record->finishedDefaultedOrDeletedMember(M); |
| M->setTrivialForCall( |
| HasTrivialABI || |
| SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI)); |
| Record->setTrivialForCallFlags(M); |
| } |
| } |
| |
| // Set triviality for the purpose of calls if this is a user-provided |
| // copy/move constructor or destructor. |
| if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor || |
| CSM == CXXDestructor) && M->isUserProvided()) { |
| M->setTrivialForCall(HasTrivialABI); |
| Record->setTrivialForCallFlags(M); |
| } |
| |
| if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() && |
| M->hasAttr<DLLExportAttr>()) { |
| if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) && |
| M->isTrivial() && |
| (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor || |
| CSM == CXXDestructor)) |
| M->dropAttr<DLLExportAttr>(); |
| |
| if (M->hasAttr<DLLExportAttr>()) { |
| DefineImplicitSpecialMember(*this, M, M->getLocation()); |
| ActOnFinishInlineFunctionDef(M); |
| } |
| } |
| } |
| } |
| |
| if (HasMethodWithOverrideControl && |
| HasOverridingMethodWithoutOverrideControl) { |
| // At least one method has the 'override' control declared. |
| // Diagnose all other overridden methods which do not have 'override' specified on them. |
| for (auto *M : Record->methods()) |
| DiagnoseAbsenceOfOverrideControl(M); |
| } |
| |
| // ms_struct is a request to use the same ABI rules as MSVC. Check |
| // whether this class uses any C++ features that are implemented |
| // completely differently in MSVC, and if so, emit a diagnostic. |
| // That diagnostic defaults to an error, but we allow projects to |
| // map it down to a warning (or ignore it). It's a fairly common |
| // practice among users of the ms_struct pragma to mass-annotate |
| // headers, sweeping up a bunch of types that the project doesn't |
| // really rely on MSVC-compatible layout for. We must therefore |
| // support "ms_struct except for C++ stuff" as a secondary ABI. |
| if (Record->isMsStruct(Context) && |
| (Record->isPolymorphic() || Record->getNumBases())) { |
| Diag(Record->getLocation(), diag::warn_cxx_ms_struct); |
| } |
| |
| checkClassLevelDLLAttribute(Record); |
| checkClassLevelCodeSegAttribute(Record); |
| |
| bool ClangABICompat4 = |
| Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4; |
| TargetInfo::CallingConvKind CCK = |
| Context.getTargetInfo().getCallingConvKind(ClangABICompat4); |
| bool CanPass = canPassInRegisters(*this, Record, CCK); |
| |
| // Do not change ArgPassingRestrictions if it has already been set to |
| // APK_CanNeverPassInRegs. |
| if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs) |
| Record->setArgPassingRestrictions(CanPass |
| ? RecordDecl::APK_CanPassInRegs |
| : RecordDecl::APK_CannotPassInRegs); |
| |
| // If canPassInRegisters returns true despite the record having a non-trivial |
| // destructor, the record is destructed in the callee. This happens only when |
| // the record or one of its subobjects has a field annotated with trivial_abi |
| // or a field qualified with ObjC __strong/__weak. |
| if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee()) |
| Record->setParamDestroyedInCallee(true); |
| else if (Record->hasNonTrivialDestructor()) |
| Record->setParamDestroyedInCallee(CanPass); |
| |
| if (getLangOpts().ForceEmitVTables) { |
| // If we want to emit all the vtables, we need to mark it as used. This |
| // is especially required for cases like vtable assumption loads. |
| MarkVTableUsed(Record->getInnerLocStart(), Record); |
| } |
| } |
| |
| /// Look up the special member function that would be called by a special |
| /// member function for a subobject of class type. |
| /// |
| /// \param Class The class type of the subobject. |
| /// \param CSM The kind of special member function. |
| /// \param FieldQuals If the subobject is a field, its cv-qualifiers. |
| /// \param ConstRHS True if this is a copy operation with a const object |
| /// on its RHS, that is, if the argument to the outer special member |
| /// function is 'const' and this is not a field marked 'mutable'. |
| static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember( |
| Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM, |
| unsigned FieldQuals, bool ConstRHS) { |
| unsigned LHSQuals = 0; |
| if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment) |
| LHSQuals = FieldQuals; |
| |
| unsigned RHSQuals = FieldQuals; |
| if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor) |
| RHSQuals = 0; |
| else if (ConstRHS) |
| RHSQuals |= Qualifiers::Const; |
| |
| return S.LookupSpecialMember(Class, CSM, |
| RHSQuals & Qualifiers::Const, |
| RHSQuals & Qualifiers::Volatile, |
| false, |
| LHSQuals & Qualifiers::Const, |
| LHSQuals & Qualifiers::Volatile); |
| } |
| |
| class Sema::InheritedConstructorInfo { |
| Sema &S; |
| SourceLocation UseLoc; |
| |
| /// A mapping from the base classes through which the constructor was |
| /// inherited to the using shadow declaration in that base class (or a null |
| /// pointer if the constructor was declared in that base class). |
| llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *> |
| InheritedFromBases; |
| |
| public: |
| InheritedConstructorInfo(Sema &S, SourceLocation UseLoc, |
| ConstructorUsingShadowDecl *Shadow) |
| : S(S), UseLoc(UseLoc) { |
| bool DiagnosedMultipleConstructedBases = false; |
| CXXRecordDecl *ConstructedBase = nullptr; |
| UsingDecl *ConstructedBaseUsing = nullptr; |
| |
| // Find the set of such base class subobjects and check that there's a |
| // unique constructed subobject. |
| for (auto *D : Shadow->redecls()) { |
| auto *DShadow = cast<ConstructorUsingShadowDecl>(D); |
| auto *DNominatedBase = DShadow->getNominatedBaseClass(); |
| auto *DConstructedBase = DShadow->getConstructedBaseClass(); |
| |
| InheritedFromBases.insert( |
| std::make_pair(DNominatedBase->getCanonicalDecl(), |
| DShadow->getNominatedBaseClassShadowDecl())); |
| if (DShadow->constructsVirtualBase()) |
| InheritedFromBases.insert( |
| std::make_pair(DConstructedBase->getCanonicalDecl(), |
| DShadow->getConstructedBaseClassShadowDecl())); |
| else |
| assert(DNominatedBase == DConstructedBase); |
| |
| // [class.inhctor.init]p2: |
| // If the constructor was inherited from multiple base class subobjects |
| // of type B, the program is ill-formed. |
| if (!ConstructedBase) { |
| ConstructedBase = DConstructedBase; |
| ConstructedBaseUsing = D->getUsingDecl(); |
| } else if (ConstructedBase != DConstructedBase && |
| !Shadow->isInvalidDecl()) { |
| if (!DiagnosedMultipleConstructedBases) { |
| S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor) |
| << Shadow->getTargetDecl(); |
| S.Diag(ConstructedBaseUsing->getLocation(), |
| diag::note_ambiguous_inherited_constructor_using) |
| << ConstructedBase; |
| DiagnosedMultipleConstructedBases = true; |
| } |
| S.Diag(D->getUsingDecl()->getLocation(), |
| diag::note_ambiguous_inherited_constructor_using) |
| << DConstructedBase; |
| } |
| } |
| |
| if (DiagnosedMultipleConstructedBases) |
| Shadow->setInvalidDecl(); |
| } |
| |
| /// Find the constructor to use for inherited construction of a base class, |
| /// and whether that base class constructor inherits the constructor from a |
| /// virtual base class (in which case it won't actually invoke it). |
| std::pair<CXXConstructorDecl *, bool> |
| findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor) const { |
| auto It = InheritedFromBases.find(Base->getCanonicalDecl()); |
| if (It == InheritedFromBases.end()) |
| return std::make_pair(nullptr, false); |
| |
| // This is an intermediary class. |
| if (It->second) |
| return std::make_pair( |
| S.findInheritingConstructor(UseLoc, Ctor, It->second), |
| It->second->constructsVirtualBase()); |
| |
| // This is the base class from which the constructor was inherited. |
| return std::make_pair(Ctor, false); |
| } |
| }; |
| |
| /// Is the special member function which would be selected to perform the |
| /// specified operation on the specified class type a constexpr constructor? |
| static bool |
| specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl, |
| Sema::CXXSpecialMember CSM, unsigned Quals, |
| bool ConstRHS, |
| CXXConstructorDecl *InheritedCtor = nullptr, |
| Sema::InheritedConstructorInfo *Inherited = nullptr) { |
| // If we're inheriting a constructor, see if we need to call it for this base |
| // class. |
| if (InheritedCtor) { |
| assert(CSM == Sema::CXXDefaultConstructor); |
| auto BaseCtor = |
| Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first; |
| if (BaseCtor) |
| return BaseCtor->isConstexpr(); |
| } |
| |
| if (CSM == Sema::CXXDefaultConstructor) |
| return ClassDecl->hasConstexprDefaultConstructor(); |
| |
| Sema::SpecialMemberOverloadResult SMOR = |
| lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS); |
| if (!SMOR.getMethod()) |
| // A constructor we wouldn't select can't be "involved in initializing" |
| // anything. |
| return true; |
| return SMOR.getMethod()->isConstexpr(); |
| } |
| |
| /// Determine whether the specified special member function would be constexpr |
| /// if it were implicitly defined. |
| static bool defaultedSpecialMemberIsConstexpr( |
| Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM, |
| bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr, |
| Sema::InheritedConstructorInfo *Inherited = nullptr) { |
| if (!S.getLangOpts().CPlusPlus11) |
| return false; |
| |
| // C++11 [dcl.constexpr]p4: |
| // In the definition of a constexpr constructor [...] |
| bool Ctor = true; |
| switch (CSM) { |
| case Sema::CXXDefaultConstructor: |
| if (Inherited) |
| break; |
| // Since default constructor lookup is essentially trivial (and cannot |
| // involve, for instance, template instantiation), we compute whether a |
| // defaulted default constructor is constexpr directly within CXXRecordDecl. |
| // |
| // This is important for performance; we need to know whether the default |
| // constructor is constexpr to determine whether the type is a literal type. |
| return ClassDecl->defaultedDefaultConstructorIsConstexpr(); |
| |
| case Sema::CXXCopyConstructor: |
| case Sema::CXXMoveConstructor: |
| // For copy or move constructors, we need to perform overload resolution. |
| break; |
| |
| case Sema::CXXCopyAssignment: |
| case Sema::CXXMoveAssignment: |
| if (!S.getLangOpts().CPlusPlus14) |
| return false; |
| // In C++1y, we need to perform overload resolution. |
| Ctor = false; |
| break; |
| |
| case Sema::CXXDestructor: |
| case Sema::CXXInvalid: |
| return false; |
| } |
| |
| // -- if the class is a non-empty union, or for each non-empty anonymous |
| // union member of a non-union class, exactly one non-static data member |
| // shall be initialized; [DR1359] |
| // |
| // If we squint, this is guaranteed, since exactly one non-static data member |
| // will be initialized (if the constructor isn't deleted), we just don't know |
| // which one. |
| if (Ctor && ClassDecl->isUnion()) |
| return CSM == Sema::CXXDefaultConstructor |
| ? ClassDecl->hasInClassInitializer() || |
| !ClassDecl->hasVariantMembers() |
| : true; |
| |
| // -- the class shall not have any virtual base classes; |
| if (Ctor && ClassDecl->getNumVBases()) |
| return false; |
| |
| // C++1y [class.copy]p26: |
| // -- [the class] is a literal type, and |
| if (!Ctor && !ClassDecl->isLiteral()) |
| return false; |
| |
| // -- every constructor involved in initializing [...] base class |
| // sub-objects shall be a constexpr constructor; |
| // -- the assignment operator selected to copy/move each direct base |
| // class is a constexpr function, and |
| for (const auto &B : ClassDecl->bases()) { |
| const RecordType *BaseType = B.getType()->getAs<RecordType>(); |
| if (!BaseType) continue; |
| |
| CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl()); |
| if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg, |
| InheritedCtor, Inherited)) |
| return false; |
| } |
| |
| // -- every constructor involved in initializing non-static data members |
| // [...] shall be a constexpr constructor; |
| // -- every non-static data member and base class sub-object shall be |
| // initialized |
| // -- for each non-static data member of X that is of class type (or array |
| // thereof), the assignment operator selected to copy/move that member is |
| // a constexpr function |
| for (const auto *F : ClassDecl->fields()) { |
| if (F->isInvalidDecl()) |
| continue; |
| if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer()) |
| continue; |
| QualType BaseType = S.Context.getBaseElementType(F->getType()); |
| if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) { |
| CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); |
| if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM, |
| BaseType.getCVRQualifiers(), |
| ConstArg && !F->isMutable())) |
| return false; |
| } else if (CSM == Sema::CXXDefaultConstructor) { |
| return false; |
| } |
| } |
| |
| // All OK, it's constexpr! |
| return true; |
| } |
| |
| static Sema::ImplicitExceptionSpecification |
| ComputeDefaultedSpecialMemberExceptionSpec( |
| Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, |
| Sema::InheritedConstructorInfo *ICI); |
| |
| static Sema::ImplicitExceptionSpecification |
| computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) { |
| auto CSM = S.getSpecialMember(MD); |
| if (CSM != Sema::CXXInvalid) |
| return ComputeDefaultedSpecialMemberExceptionSpec(S, Loc, MD, CSM, nullptr); |
| |
| auto *CD = cast<CXXConstructorDecl>(MD); |
| assert(CD->getInheritedConstructor() && |
| "only special members have implicit exception specs"); |
| Sema::InheritedConstructorInfo ICI( |
| S, Loc, CD->getInheritedConstructor().getShadowDecl()); |
| return ComputeDefaultedSpecialMemberExceptionSpec( |
| S, Loc, CD, Sema::CXXDefaultConstructor, &ICI); |
| } |
| |
| static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S, |
| CXXMethodDecl *MD) { |
| FunctionProtoType::ExtProtoInfo EPI; |
| |
| // Build an exception specification pointing back at this member. |
| EPI.ExceptionSpec.Type = EST_Unevaluated; |
| EPI.ExceptionSpec.SourceDecl = MD; |
| |
| // Set the calling convention to the default for C++ instance methods. |
| EPI.ExtInfo = EPI.ExtInfo.withCallingConv( |
| S.Context.getDefaultCallingConvention(/*IsVariadic=*/false, |
| /*IsCXXMethod=*/true)); |
| return EPI; |
| } |
| |
| void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) { |
| const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); |
| if (FPT->getExceptionSpecType() != EST_Unevaluated) |
| return; |
| |
| // Evaluate the exception specification. |
| auto IES = computeImplicitExceptionSpec(*this, Loc, MD); |
| auto ESI = IES.getExceptionSpec(); |
| |
| // Update the type of the special member to use it. |
| UpdateExceptionSpec(MD, ESI); |
| |
| // A user-provided destructor can be defined outside the class. When that |
| // happens, be sure to update the exception specification on both |
| // declarations. |
| const FunctionProtoType *CanonicalFPT = |
| MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>(); |
| if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated) |
| UpdateExceptionSpec(MD->getCanonicalDecl(), ESI); |
| } |
| |
| void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { |
| CXXRecordDecl *RD = MD->getParent(); |
| CXXSpecialMember CSM = getSpecialMember(MD); |
| |
| assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid && |
| "not an explicitly-defaulted special member"); |
| |
| // Whether this was the first-declared instance of the constructor. |
| // This affects whether we implicitly add an exception spec and constexpr. |
| bool First = MD == MD->getCanonicalDecl(); |
| |
| bool HadError = false; |
| |
| // C++11 [dcl.fct.def.default]p1: |
| // A function that is explicitly defaulted shall |
| // -- be a special member function (checked elsewhere), |
| // -- have the same type (except for ref-qualifiers, and except that a |
| // copy operation can take a non-const reference) as an implicit |
| // declaration, and |
| // -- not have default arguments. |
| unsigned ExpectedParams = 1; |
| if (CSM == CXXDefaultConstructor || CSM == CXXDestructor) |
| ExpectedParams = 0; |
| if (MD->getNumParams() != ExpectedParams) { |
| // This also checks for default arguments: a copy or move constructor with a |
| // default argument is classified as a default constructor, and assignment |
| // operations and destructors can't have default arguments. |
| Diag(MD->getLocation(), diag::err_defaulted_special_member_params) |
| << CSM << MD->getSourceRange(); |
| HadError = true; |
| } else if (MD->isVariadic()) { |
| Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic) |
| << CSM << MD->getSourceRange(); |
| HadError = true; |
| } |
| |
| const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>(); |
| |
| bool CanHaveConstParam = false; |
| if (CSM == CXXCopyConstructor) |
| CanHaveConstParam = RD->implicitCopyConstructorHasConstParam(); |
| else if (CSM == CXXCopyAssignment) |
| CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam(); |
| |
| QualType ReturnType = Context.VoidTy; |
| if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) { |
| // Check for return type matching. |
| ReturnType = Type->getReturnType(); |
| QualType ExpectedReturnType = |
| Context.getLValueReferenceType(Context.getTypeDeclType(RD)); |
| if (!Context.hasSameType(ReturnType, ExpectedReturnType)) { |
| Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type) |
| << (CSM == CXXMoveAssignment) << ExpectedReturnType; |
| HadError = true; |
| } |
| |
| // A defaulted special member cannot have cv-qualifiers. |
| if (Type->getTypeQuals()) { |
| Diag(MD->getLocation(), diag::err_defaulted_special_member_quals) |
| << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14; |
| HadError = true; |
| } |
| } |
| |
| // Check for parameter type matching. |
| QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType(); |
| bool HasConstParam = false; |
| if (ExpectedParams && ArgType->isReferenceType()) { |
| // Argument must be reference to possibly-const T. |
| QualType ReferentType = ArgType->getPointeeType(); |
| HasConstParam = ReferentType.isConstQualified(); |
| |
| if (ReferentType.isVolatileQualified()) { |
| Diag(MD->getLocation(), |
| diag::err_defaulted_special_member_volatile_param) << CSM; |
| HadError = true; |
| } |
| |
| if (HasConstParam && !CanHaveConstParam) { |
| if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) { |
| Diag(MD->getLocation(), |
| diag::err_defaulted_special_member_copy_const_param) |
| << (CSM == CXXCopyAssignment); |
| // FIXME: Explain why this special member can't be const. |
| } else { |
| Diag(MD->getLocation(), |
| diag::err_defaulted_special_member_move_const_param) |
| << (CSM == CXXMoveAssignment); |
| } |
| HadError = true; |
| } |
| } else if (ExpectedParams) { |
| // A copy assignment operator can take its argument by value, but a |
| // defaulted one cannot. |
| assert(CSM == CXXCopyAssignment && "unexpected non-ref argument"); |
| Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref); |
| HadError = true; |
| } |
| |
| // C++11 [dcl.fct.def.default]p2: |
| // An explicitly-defaulted function may be declared constexpr only if it |
| // would have been implicitly declared as constexpr, |
| // Do not apply this rule to members of class templates, since core issue 1358 |
| // makes such functions always instantiate to constexpr functions. For |
| // functions which cannot be constexpr (for non-constructors in C++11 and for |
| // destructors in C++1y), this is checked elsewhere. |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, |
| HasConstParam); |
| if ((getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD) |
| : isa<CXXConstructorDecl>(MD)) && |
| MD->isConstexpr() && !Constexpr && |
| MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { |
| Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM; |
| // FIXME: Explain why the special member can't be constexpr. |
| HadError = true; |
| } |
| |
| // and may have an explicit exception-specification only if it is compatible |
| // with the exception-specification on the implicit declaration. |
| if (Type->hasExceptionSpec()) { |
| // Delay the check if this is the first declaration of the special member, |
| // since we may not have parsed some necessary in-class initializers yet. |
| if (First) { |
| // If the exception specification needs to be instantiated, do so now, |
| // before we clobber it with an EST_Unevaluated specification below. |
| if (Type->getExceptionSpecType() == EST_Uninstantiated) { |
| InstantiateExceptionSpec(MD->getLocStart(), MD); |
| Type = MD->getType()->getAs<FunctionProtoType>(); |
| } |
| DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); |
| } else |
| CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type); |
| } |
| |
| // If a function is explicitly defaulted on its first declaration, |
| if (First) { |
| // -- it is implicitly considered to be constexpr if the implicit |
| // definition would be, |
| MD->setConstexpr(Constexpr); |
| |
| // -- it is implicitly considered to have the same exception-specification |
| // as if it had been implicitly declared, |
| FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); |
| EPI.ExceptionSpec.Type = EST_Unevaluated; |
| EPI.ExceptionSpec.SourceDecl = MD; |
| MD->setType(Context.getFunctionType(ReturnType, |
| llvm::makeArrayRef(&ArgType, |
| ExpectedParams), |
| EPI)); |
| } |
| |
| if (ShouldDeleteSpecialMember(MD, CSM)) { |
| if (First) { |
| SetDeclDeleted(MD, MD->getLocation()); |
| } else { |
| // C++11 [dcl.fct.def.default]p4: |
| // [For a] user-provided explicitly-defaulted function [...] if such a |
| // function is implicitly defined as deleted, the program is ill-formed. |
| Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM; |
| ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true); |
| HadError = true; |
| } |
| } |
| |
| if (HadError) |
| MD->setInvalidDecl(); |
| } |
| |
| /// Check whether the exception specification provided for an |
| /// explicitly-defaulted special member matches the exception specification |
| /// that would have been generated for an implicit special member, per |
| /// C++11 [dcl.fct.def.default]p2. |
| void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( |
| CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { |
| // If the exception specification was explicitly specified but hadn't been |
| // parsed when the method was defaulted, grab it now. |
| if (SpecifiedType->getExceptionSpecType() == EST_Unparsed) |
| SpecifiedType = |
| MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>(); |
| |
| // Compute the implicit exception specification. |
| CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, |
| /*IsCXXMethod=*/true); |
| FunctionProtoType::ExtProtoInfo EPI(CC); |
| auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD); |
| EPI.ExceptionSpec = IES.getExceptionSpec(); |
| const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( |
| Context.getFunctionType(Context.VoidTy, None, EPI)); |
| |
| // Ensure that it matches. |
| CheckEquivalentExceptionSpec( |
| PDiag(diag::err_incorrect_defaulted_exception_spec) |
| << getSpecialMember(MD), PDiag(), |
| ImplicitType, SourceLocation(), |
| SpecifiedType, MD->getLocation()); |
| } |
| |
| void Sema::CheckDelayedMemberExceptionSpecs() { |
| decltype(DelayedExceptionSpecChecks) Checks; |
| decltype(DelayedDefaultedMemberExceptionSpecs) Specs; |
| |
| std::swap(Checks, DelayedExceptionSpecChecks); |
| std::swap(Specs, DelayedDefaultedMemberExceptionSpecs); |
| |
| // Perform any deferred checking of exception specifications for virtual |
| // destructors. |
| for (auto &Check : Checks) |
| CheckOverridingFunctionExceptionSpec(Check.first, Check.second); |
| |
| // Check that any explicitly-defaulted methods have exception specifications |
| // compatible with their implicit exception specifications. |
| for (auto &Spec : Specs) |
| CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second); |
| } |
| |
| namespace { |
| /// CRTP base class for visiting operations performed by a special member |
| /// function (or inherited constructor). |
| template<typename Derived> |
| struct SpecialMemberVisitor { |
| Sema &S; |
| CXXMethodDecl *MD; |
| Sema::CXXSpecialMember CSM; |
| Sema::InheritedConstructorInfo *ICI; |
| |
| // Properties of the special member, computed for convenience. |
| bool IsConstructor = false, IsAssignment = false, ConstArg = false; |
| |
| SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, |
| Sema::InheritedConstructorInfo *ICI) |
| : S(S), MD(MD), CSM(CSM), ICI(ICI) { |
| switch (CSM) { |
| case Sema::CXXDefaultConstructor: |
| case Sema::CXXCopyConstructor: |
| case Sema::CXXMoveConstructor: |
| IsConstructor = true; |
| break; |
| case Sema::CXXCopyAssignment: |
| case Sema::CXXMoveAssignment: |
| IsAssignment = true; |
| break; |
| case Sema::CXXDestructor: |
| break; |
| case Sema::CXXInvalid: |
| llvm_unreachable("invalid special member kind"); |
| } |
| |
| if (MD->getNumParams()) { |
| if (const ReferenceType *RT = |
| MD->getParamDecl(0)->getType()->getAs<ReferenceType>()) |
| ConstArg = RT->getPointeeType().isConstQualified(); |
| } |
| } |
| |
| Derived &getDerived() { return static_cast<Derived&>(*this); } |
| |
| /// Is this a "move" special member? |
| bool isMove() const { |
| return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment; |
| } |
| |
| /// Look up the corresponding special member in the given class. |
| Sema::SpecialMemberOverloadResult lookupIn(CXXRecordDecl *Class, |
| unsigned Quals, bool IsMutable) { |
| return lookupCallFromSpecialMember(S, Class, CSM, Quals, |
| ConstArg && !IsMutable); |
| } |
| |
| /// Look up the constructor for the specified base class to see if it's |
| /// overridden due to this being an inherited constructor. |
| Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) { |
| if (!ICI) |
| return {}; |
| assert(CSM == Sema::CXXDefaultConstructor); |
| auto *BaseCtor = |
| cast<CXXConstructorDecl>(MD)->getInheritedConstructor().getConstructor(); |
| if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first) |
| return MD; |
| return {}; |
| } |
| |
| /// A base or member subobject. |
| typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject; |
| |
| /// Get the location to use for a subobject in diagnostics. |
| static SourceLocation getSubobjectLoc(Subobject Subobj) { |
| // FIXME: For an indirect virtual base, the direct base leading to |
| // the indirect virtual base would be a more useful choice. |
| if (auto *B = Subobj.dyn_cast<CXXBaseSpecifier*>()) |
| return B->getBaseTypeLoc(); |
| else |
| return Subobj.get<FieldDecl*>()->getLocation(); |
| } |
| |
| enum BasesToVisit { |
| /// Visit all non-virtual (direct) bases. |
| VisitNonVirtualBases, |
| /// Visit all direct bases, virtual or not. |
| VisitDirectBases, |
| /// Visit all non-virtual bases, and all virtual bases if the class |
| /// is not abstract. |
| VisitPotentiallyConstructedBases, |
| /// Visit all direct or virtual bases. |
| VisitAllBases |
| }; |
| |
| // Visit the bases and members of the class. |
| bool visit(BasesToVisit Bases) { |
| CXXRecordDecl *RD = MD->getParent(); |
| |
| if (Bases == VisitPotentiallyConstructedBases) |
| Bases = RD->isAbstract() ? VisitNonVirtualBases : VisitAllBases; |
| |
| for (auto &B : RD->bases()) |
| if ((Bases == VisitDirectBases || !B.isVirtual()) && |
| getDerived().visitBase(&B)) |
| return true; |
| |
| if (Bases == VisitAllBases) |
| for (auto &B : RD->vbases()) |
| if (getDerived().visitBase(&B)) |
| return true; |
| |
| for (auto *F : RD->fields()) |
| if (!F->isInvalidDecl() && !F->isUnnamedBitfield() && |
| getDerived().visitField(F)) |
| return true; |
| |
| return false; |
| } |
| }; |
| } |
| |
| namespace { |
| struct SpecialMemberDeletionInfo |
| : SpecialMemberVisitor<SpecialMemberDeletionInfo> { |
| bool Diagnose; |
| |
| SourceLocation Loc; |
| |
| bool AllFieldsAreConst; |
| |
| SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD, |
| Sema::CXXSpecialMember CSM, |
| Sema::InheritedConstructorInfo *ICI, bool Diagnose) |
| : SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose), |
| Loc(MD->getLocation()), AllFieldsAreConst(true) {} |
| |
| bool inUnion() const { return MD->getParent()->isUnion(); } |
| |
| Sema::CXXSpecialMember getEffectiveCSM() { |
| return ICI ? Sema::CXXInvalid : CSM; |
| } |
| |
| bool visitBase(CXXBaseSpecifier *Base) { return shouldDeleteForBase(Base); } |
| bool visitField(FieldDecl *Field) { return shouldDeleteForField(Field); } |
| |
| bool shouldDeleteForBase(CXXBaseSpecifier *Base); |
| bool shouldDeleteForField(FieldDecl *FD); |
| bool shouldDeleteForAllConstMembers(); |
| |
| bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj, |
| unsigned Quals); |
| bool shouldDeleteForSubobjectCall(Subobject Subobj, |
| Sema::SpecialMemberOverloadResult SMOR, |
| bool IsDtorCallInCtor); |
| |
| bool isAccessible(Subobject Subobj, CXXMethodDecl *D); |
| }; |
| } |
| |
| /// Is the given special member inaccessible when used on the given |
| /// sub-object. |
| bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj, |
| CXXMethodDecl *target) { |
| /// If we're operating on a base class, the object type is the |
| /// type of this special member. |
| QualType objectTy; |
| AccessSpecifier access = target->getAccess(); |
| if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) { |
| objectTy = S.Context.getTypeDeclType(MD->getParent()); |
| access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access); |
| |
| // If we're operating on a field, the object type is the type of the field. |
| } else { |
| objectTy = S.Context.getTypeDeclType(target->getParent()); |
| } |
| |
| return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy); |
| } |
| |
| /// Check whether we should delete a special member due to the implicit |
| /// definition containing a call to a special member of a subobject. |
| bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall( |
| Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR, |
| bool IsDtorCallInCtor) { |
| CXXMethodDecl *Decl = SMOR.getMethod(); |
| FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); |
| |
| int DiagKind = -1; |
| |
| if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) |
| DiagKind = !Decl ? 0 : 1; |
| else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) |
| DiagKind = 2; |
| else if (!isAccessible(Subobj, Decl)) |
| DiagKind = 3; |
| else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() && |
| !Decl->isTrivial()) { |
| // A member of a union must have a trivial corresponding special member. |
| // As a weird special case, a destructor call from a union's constructor |
| // must be accessible and non-deleted, but need not be trivial. Such a |
| // destructor is never actually called, but is semantically checked as |
| // if it were. |
| DiagKind = 4; |
| } |
| |
| if (DiagKind == -1) |
| return false; |
| |
| if (Diagnose) { |
| if (Field) { |
| S.Diag(Field->getLocation(), |
| diag::note_deleted_special_member_class_subobject) |
| << getEffectiveCSM() << MD->getParent() << /*IsField*/true |
| << Field << DiagKind << IsDtorCallInCtor; |
| } else { |
| CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>(); |
| S.Diag(Base->getLocStart(), |
| diag::note_deleted_special_member_class_subobject) |
| << getEffectiveCSM() << MD->getParent() << /*IsField*/false |
| << Base->getType() << DiagKind << IsDtorCallInCtor; |
| } |
| |
| if (DiagKind == 1) |
| S.NoteDeletedFunction(Decl); |
| // FIXME: Explain inaccessibility if DiagKind == 3. |
| } |
| |
| return true; |
| } |
| |
| /// Check whether we should delete a special member function due to having a |
| /// direct or virtual base class or non-static data member of class type M. |
| bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject( |
| CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) { |
| FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); |
| bool IsMutable = Field && Field->isMutable(); |
| |
| // C++11 [class.ctor]p5: |
| // -- any direct or virtual base class, or non-static data member with no |
| // brace-or-equal-initializer, has class type M (or array thereof) and |
| // either M has no default constructor or overload resolution as applied |
| // to M's default constructor results in an ambiguity or in a function |
| // that is deleted or inaccessible |
| // C++11 [class.copy]p11, C++11 [class.copy]p23: |
| // -- a direct or virtual base class B that cannot be copied/moved because |
| // overload resolution, as applied to B's corresponding special member, |
| // results in an ambiguity or a function that is deleted or inaccessible |
| // from the defaulted special member |
| // C++11 [class.dtor]p5: |
| // -- any direct or virtual base class [...] has a type with a destructor |
| // that is deleted or inaccessible |
| if (!(CSM == Sema::CXXDefaultConstructor && |
| Field && Field->hasInClassInitializer()) && |
| shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable), |
| false)) |
| return true; |
| |
| // C++11 [class.ctor]p5, C++11 [class.copy]p11: |
| // -- any direct or virtual base class or non-static data member has a |
| // type with a destructor that is deleted or inaccessible |
| if (IsConstructor) { |
| Sema::SpecialMemberOverloadResult SMOR = |
| S.LookupSpecialMember(Class, Sema::CXXDestructor, |
| false, false, false, false, false); |
| if (shouldDeleteForSubobjectCall(Subobj, SMOR, true)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Check whether we should delete a special member function due to the class |
| /// having a particular direct or virtual base class. |
| bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) { |
| CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl(); |
| // If program is correct, BaseClass cannot be null, but if it is, the error |
| // must be reported elsewhere. |
| if (!BaseClass) |
| return false; |
| // If we have an inheriting constructor, check whether we're calling an |
| // inherited constructor instead of a default constructor. |
| Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); |
| if (auto *BaseCtor = SMOR.getMethod()) { |
| // Note that we do not check access along this path; other than that, |
| // this is the same as shouldDeleteForSubobjectCall(Base, BaseCtor, false); |
| // FIXME: Check that the base has a usable destructor! Sink this into |
| // shouldDeleteForClassSubobject. |
| if (BaseCtor->isDeleted() && Diagnose) { |
| S.Diag(Base->getLocStart(), |
| diag::note_deleted_special_member_class_subobject) |
| << getEffectiveCSM() << MD->getParent() << /*IsField*/false |
| << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/false; |
| S.NoteDeletedFunction(BaseCtor); |
| } |
| return BaseCtor->isDeleted(); |
| } |
| return shouldDeleteForClassSubobject(BaseClass, Base, 0); |
| } |
| |
| /// Check whether we should delete a special member function due to the class |
| /// having a particular non-static data member. |
| bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) { |
| QualType FieldType = S.Context.getBaseElementType(FD->getType()); |
| CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl(); |
| |
| if (CSM == Sema::CXXDefaultConstructor) { |
| // For a default constructor, all references must be initialized in-class |
| // and, if a union, it must have a non-const member. |
| if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) { |
| if (Diagnose) |
| S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) |
| << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0; |
| return true; |
| } |
| // C++11 [class.ctor]p5: any non-variant non-static data member of |
| // const-qualified type (or array thereof) with no |
| // brace-or-equal-initializer does not have a user-provided default |
| // constructor. |
| if (!inUnion() && FieldType.isConstQualified() && |
| !FD->hasInClassInitializer() && |
| (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) { |
| if (Diagnose) |
| S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field) |
| << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1; |
| return true; |
| } |
| |
| if (inUnion() && !FieldType.isConstQualified()) |
| AllFieldsAreConst = false; |
| } else if (CSM == Sema::CXXCopyConstructor) { |
| // For a copy constructor, data members must not be of rvalue reference |
| // type. |
| if (FieldType->isRValueReferenceType()) { |
| if (Diagnose) |
| S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference) |
| << MD->getParent() << FD << FieldType; |
| return true; |
| } |
| } else if (IsAssignment) { |
| // For an assignment operator, data members must not be of reference type. |
| if (FieldType->isReferenceType()) { |
| if (Diagnose) |
| S.Diag(FD->getLocation(), diag::note_deleted_assign_field) |
| << isMove() << MD->getParent() << FD << FieldType << /*Reference*/0; |
| return true; |
| } |
| if (!FieldRecord && FieldType.isConstQualified()) { |
| // C++11 [class.copy]p23: |
| // -- a non-static data member of const non-class type (or array thereof) |
| if (Diagnose) |
| S.Diag(FD->getLocation(), diag::note_deleted_assign_field) |
| << isMove() << MD->getParent() << FD << FD->getType() << /*Const*/1; |
| return true; |
| } |
| } |
| |
| if (FieldRecord) { |
| // Some additional restrictions exist on the variant members. |
| if (!inUnion() && FieldRecord->isUnion() && |
| FieldRecord->isAnonymousStructOrUnion()) { |
| bool AllVariantFieldsAreConst = true; |
| |
| // FIXME: Handle anonymous unions declared within anonymous unions. |
| for (auto *UI : FieldRecord->fields()) { |
| QualType UnionFieldType = S.Context.getBaseElementType(UI->getType()); |
| |
| if (!UnionFieldType.isConstQualified()) |
| AllVariantFieldsAreConst = false; |
| |
| CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl(); |
| if (UnionFieldRecord && |
| shouldDeleteForClassSubobject(UnionFieldRecord, UI, |
| UnionFieldType.getCVRQualifiers())) |
| return true; |
| } |
| |
| // At least one member in each anonymous union must be non-const |
| if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst && |
| !FieldRecord->field_empty()) { |
| if (Diagnose) |
| S.Diag(FieldRecord->getLocation(), |
| diag::note_deleted_default_ctor_all_const) |
| << !!ICI << MD->getParent() << /*anonymous union*/1; |
| return true; |
| } |
| |
| // Don't check the implicit member of the anonymous union type. |
| // This is technically non-conformant, but sanity demands it. |
| return false; |
| } |
| |
| if (shouldDeleteForClassSubobject(FieldRecord, FD, |
| FieldType.getCVRQualifiers())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// C++11 [class.ctor] p5: |
| /// A defaulted default constructor for a class X is defined as deleted if |
| /// X is a union and all of its variant members are of const-qualified type. |
| bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() { |
| // This is a silly definition, because it gives an empty union a deleted |
| // default constructor. Don't do that. |
| if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) { |
| bool AnyFields = false; |
| for (auto *F : MD->getParent()->fields()) |
| if ((AnyFields = !F->isUnnamedBitfield())) |
| break; |
| if (!AnyFields) |
| return false; |
| if (Diagnose) |
| S.Diag(MD->getParent()->getLocation(), |
| diag::note_deleted_default_ctor_all_const) |
| << !!ICI << MD->getParent() << /*not anonymous union*/0; |
| return true; |
| } |
| return false; |
| } |
| |
| /// Determine whether a defaulted special member function should be defined as |
| /// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11, |
| /// C++11 [class.copy]p23, and C++11 [class.dtor]p5. |
| bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, |
| InheritedConstructorInfo *ICI, |
| bool Diagnose) { |
| if (MD->isInvalidDecl()) |
| return false; |
| CXXRecordDecl *RD = MD->getParent(); |
| assert(!RD->isDependentType() && "do deletion after instantiation"); |
| if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl()) |
| return false; |
| |
| // C++11 [expr.lambda.prim]p19: |
| // The closure type associated with a lambda-expression has a |
| // deleted (8.4.3) default constructor and a deleted copy |
| // assignment operator. |
| if (RD->isLambda() && |
| (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) { |
| if (Diagnose) |
| Diag(RD->getLocation(), diag::note_lambda_decl); |
| return true; |
| } |
| |
| // For an anonymous struct or union, the copy and assignment special members |
| // will never be used, so skip the check. For an anonymous union declared at |
| // namespace scope, the constructor and destructor are used. |
| if (CSM != CXXDefaultConstructor && CSM != CXXDestructor && |
| RD->isAnonymousStructOrUnion()) |
| return false; |
| |
| // C++11 [class.copy]p7, p18: |
| // If the class definition declares a move constructor or move assignment |
| // operator, an implicitly declared copy constructor or copy assignment |
| // operator is defined as deleted. |
| if (MD->isImplicit() && |
| (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) { |
| CXXMethodDecl *UserDeclaredMove = nullptr; |
| |
| // In Microsoft mode up to MSVC 2013, a user-declared move only causes the |
| // deletion of the corresponding copy operation, not both copy operations. |
| // MSVC 2015 has adopted the standards conforming behavior. |
| bool DeletesOnlyMatchingCopy = |
| getLangOpts().MSVCCompat && |
| !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015); |
| |
| if (RD->hasUserDeclaredMoveConstructor() && |
| (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) { |
| if (!Diagnose) return true; |
| |
| // Find any user-declared move constructor. |
| for (auto *I : RD->ctors()) { |
| if (I->isMoveConstructor()) { |
| UserDeclaredMove = I; |
| break; |
| } |
| } |
| assert(UserDeclaredMove); |
| } else if (RD->hasUserDeclaredMoveAssignment() && |
| (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) { |
| if (!Diagnose) return true; |
| |
| // Find any user-declared move assignment operator. |
| for (auto *I : RD->methods()) { |
| if (I->isMoveAssignmentOperator()) { |
| UserDeclaredMove = I; |
| break; |
| } |
| } |
| assert(UserDeclaredMove); |
| } |
| |
| if (UserDeclaredMove) { |
| Diag(UserDeclaredMove->getLocation(), |
| diag::note_deleted_copy_user_declared_move) |
| << (CSM == CXXCopyAssignment) << RD |
| << UserDeclaredMove->isMoveAssignmentOperator(); |
| return true; |
| } |
| } |
| |
| // Do access control from the special member function |
| ContextRAII MethodContext(*this, MD); |
| |
| // C++11 [class.dtor]p5: |
| // -- for a virtual destructor, lookup of the non-array deallocation function |
| // results in an ambiguity or in a function that is deleted or inaccessible |
| if (CSM == CXXDestructor && MD->isVirtual()) { |
| FunctionDecl *OperatorDelete = nullptr; |
| DeclarationName Name = |
| Context.DeclarationNames.getCXXOperatorName(OO_Delete); |
| if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name, |
| OperatorDelete, /*Diagnose*/false)) { |
| if (Diagnose) |
| Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete); |
| return true; |
| } |
| } |
| |
| SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose); |
| |
| // Per DR1611, do not consider virtual bases of constructors of abstract |
| // classes, since we are not going to construct them. |
| // Per DR1658, do not consider virtual bases of destructors of abstract |
| // classes either. |
| // Per DR2180, for assignment operators we only assign (and thus only |
| // consider) direct bases. |
| if (SMI.visit(SMI.IsAssignment ? SMI.VisitDirectBases |
| : SMI.VisitPotentiallyConstructedBases)) |
| return true; |
| |
| if (SMI.shouldDeleteForAllConstMembers()) |
| return true; |
| |
| if (getLangOpts().CUDA) { |
| // We should delete the special member in CUDA mode if target inference |
| // failed. |
| return inferCUDATargetForImplicitSpecialMember(RD, CSM, MD, SMI.ConstArg, |
| Diagnose); |
| } |
| |
| return false; |
| } |
| |
| /// Perform lookup for a special member of the specified kind, and determine |
| /// whether it is trivial. If the triviality can be determined without the |
| /// lookup, skip it. This is intended for use when determining whether a |
| /// special member of a containing object is trivial, and thus does not ever |
| /// perform overload resolution for default constructors. |
| /// |
| /// If \p Selected is not \c NULL, \c *Selected will be filled in with the |
| /// member that was most likely to be intended to be trivial, if any. |
| /// |
| /// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to |
| /// determine whether the special member is trivial. |
| static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD, |
| Sema::CXXSpecialMember CSM, unsigned Quals, |
| bool ConstRHS, |
| Sema::TrivialABIHandling TAH, |
| CXXMethodDecl **Selected) { |
| if (Selected) |
| *Selected = nullptr; |
| |
| switch (CSM) { |
| case Sema::CXXInvalid: |
| llvm_unreachable("not a special member"); |
| |
| case Sema::CXXDefaultConstructor: |
| // C++11 [class.ctor]p5: |
| // A default constructor is trivial if: |
| // - all the [direct subobjects] have trivial default constructors |
| // |
| // Note, no overload resolution is performed in this case. |
| if (RD->hasTrivialDefaultConstructor()) |
| return true; |
| |
| if (Selected) { |
| // If there's a default constructor which could have been trivial, dig it |
| // out. Otherwise, if there's any user-provided default constructor, point |
| // to that as an example of why there's not a trivial one. |
| CXXConstructorDecl *DefCtor = nullptr; |
| if (RD->needsImplicitDefaultConstructor()) |
| S.DeclareImplicitDefaultConstructor(RD); |
| for (auto *CI : RD->ctors()) { |
| if (!CI->isDefaultConstructor()) |
| continue; |
| DefCtor = CI; |
| if (!DefCtor->isUserProvided()) |
| break; |
| } |
| |
| *Selected = DefCtor; |
| } |
| |
| return false; |
| |
| case Sema::CXXDestructor: |
| // C++11 [class.dtor]p5: |
| // A destructor is trivial if: |
| // - all the direct [subobjects] have trivial destructors |
| if (RD->hasTrivialDestructor() || |
| (TAH == Sema::TAH_ConsiderTrivialABI && |
| RD->hasTrivialDestructorForCall())) |
| return true; |
| |
| if (Selected) { |
| if (RD->needsImplicitDestructor()) |
| S.DeclareImplicitDestructor(RD); |
| *Selected = RD->getDestructor(); |
| } |
| |
| return false; |
| |
| case Sema::CXXCopyConstructor: |
| // C++11 [class.copy]p12: |
| // A copy constructor is trivial if: |
| // - the constructor selected to copy each direct [subobject] is trivial |
| if (RD->hasTrivialCopyConstructor() || |
| (TAH == Sema::TAH_ConsiderTrivialABI && |
| RD->hasTrivialCopyConstructorForCall())) { |
| if (Quals == Qualifiers::Const) |
| // We must either select the trivial copy constructor or reach an |
| // ambiguity; no need to actually perform overload resolution. |
| return true; |
| } else if (!Selected) { |
| return false; |
| } |
| // In C++98, we are not supposed to perform overload resolution here, but we |
| // treat that as a language defect, as suggested on cxx-abi-dev, to treat |
| // cases like B as having a non-trivial copy constructor: |
| // struct A { template<typename T> A(T&); }; |
| // struct B { mutable A a; }; |
| goto NeedOverloadResolution; |
| |
| case Sema::CXXCopyAssignment: |
| // C++11 [class.copy]p25: |
| // A copy assignment operator is trivial if: |
| // - the assignment operator selected to copy each direct [subobject] is |
| // trivial |
| if (RD->hasTrivialCopyAssignment()) { |
| if (Quals == Qualifiers::Const) |
| return true; |
| } else if (!Selected) { |
| return false; |
| } |
| // In C++98, we are not supposed to perform overload resolution here, but we |
| // treat that as a language defect. |
| goto NeedOverloadResolution; |
| |
| case Sema::CXXMoveConstructor: |
| case Sema::CXXMoveAssignment: |
| NeedOverloadResolution: |
| Sema::SpecialMemberOverloadResult SMOR = |
| lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS); |
| |
| // The standard doesn't describe how to behave if the lookup is ambiguous. |
| // We treat it as not making the member non-trivial, just like the standard |
| // mandates for the default constructor. This should rarely matter, because |
| // the member will also be deleted. |
| if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous) |
| return true; |
| |
| if (!SMOR.getMethod()) { |
| assert(SMOR.getKind() == |
| Sema::SpecialMemberOverloadResult::NoMemberOrDeleted); |
| return false; |
| } |
| |
| // We deliberately don't check if we found a deleted special member. We're |
| // not supposed to! |
| if (Selected) |
| *Selected = SMOR.getMethod(); |
| |
| if (TAH == Sema::TAH_ConsiderTrivialABI && |
| (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor)) |
| return SMOR.getMethod()->isTrivialForCall(); |
| return SMOR.getMethod()->isTrivial(); |
| } |
| |
| llvm_unreachable("unknown special method kind"); |
| } |
| |
| static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) { |
| for (auto *CI : RD->ctors()) |
| if (!CI->isImplicit()) |
| return CI; |
| |
| // Look for constructor templates. |
| typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter; |
| for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) { |
| if (CXXConstructorDecl *CD = |
| dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl())) |
| return CD; |
| } |
| |
| return nullptr; |
| } |
| |
| /// The kind of subobject we are checking for triviality. The values of this |
| /// enumeration are used in diagnostics. |
| enum TrivialSubobjectKind { |
| /// The subobject is a base class. |
| TSK_BaseClass, |
| /// The subobject is a non-static data member. |
| TSK_Field, |
| /// The object is actually the complete object. |
| TSK_CompleteObject |
| }; |
| |
| /// Check whether the special member selected for a given type would be trivial. |
| static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc, |
| QualType SubType, bool ConstRHS, |
| Sema::CXXSpecialMember CSM, |
| TrivialSubobjectKind Kind, |
| Sema::TrivialABIHandling TAH, bool Diagnose) { |
| CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl(); |
| if (!SubRD) |
| return true; |
| |
| CXXMethodDecl *Selected; |
| if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(), |
| ConstRHS, TAH, Diagnose ? &Selected : nullptr)) |
| return true; |
| |
| if (Diagnose) { |
| if (ConstRHS) |
| SubType.addConst(); |
| |
| if (!Selected && CSM == Sema::CXXDefaultConstructor) { |
| S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor) |
| << Kind << SubType.getUnqualifiedType(); |
| if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD)) |
| S.Diag(CD->getLocation(), diag::note_user_declared_ctor); |
| } else if (!Selected) |
| S.Diag(SubobjLoc, diag::note_nontrivial_no_copy) |
| << Kind << SubType.getUnqualifiedType() << CSM << SubType; |
| else if (Selected->isUserProvided()) { |
| if (Kind == TSK_CompleteObject) |
| S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided) |
| << Kind << SubType.getUnqualifiedType() << CSM; |
| else { |
| S.Diag(SubobjLoc, diag::note_nontrivial_user_provided) |
| << Kind << SubType.getUnqualifiedType() << CSM; |
| S.Diag(Selected->getLocation(), diag::note_declared_at); |
| } |
| } else { |
| if (Kind != TSK_CompleteObject) |
| S.Diag(SubobjLoc, diag::note_nontrivial_subobject) |
| << Kind << SubType.getUnqualifiedType() << CSM; |
| |
| // Explain why the defaulted or deleted special member isn't trivial. |
| S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI, |
| Diagnose); |
| } |
| } |
| |
| return false; |
| } |
| |
| /// Check whether the members of a class type allow a special member to be |
| /// trivial. |
| static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD, |
| Sema::CXXSpecialMember CSM, |
| bool ConstArg, |
| Sema::TrivialABIHandling TAH, |
| bool Diagnose) { |
| for (const auto *FI : RD->fields()) { |
| if (FI->isInvalidDecl() || FI->isUnnamedBitfield()) |
| continue; |
| |
| QualType FieldType = S.Context.getBaseElementType(FI->getType()); |
| |
| // Pretend anonymous struct or union members are members of this class. |
| if (FI->isAnonymousStructOrUnion()) { |
| if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(), |
| CSM, ConstArg, TAH, Diagnose)) |
| return false; |
| continue; |
| } |
| |
| // C++11 [class.ctor]p5: |
| // A default constructor is trivial if [...] |
| // -- no non-static data member of its class has a |
| // brace-or-equal-initializer |
| if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) { |
| if (Diagnose) |
| S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI; |
| return false; |
| } |
| |
| // Objective C ARC 4.3.5: |
| // [...] nontrivally ownership-qualified types are [...] not trivially |
| // default constructible, copy constructible, move constructible, copy |
| // assignable, move assignable, or destructible [...] |
| if (FieldType.hasNonTrivialObjCLifetime()) { |
| if (Diagnose) |
| S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership) |
| << RD << FieldType.getObjCLifetime(); |
| return false; |
| } |
| |
| bool ConstRHS = ConstArg && !FI->isMutable(); |
| if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS, |
| CSM, TSK_Field, TAH, Diagnose)) |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /// Diagnose why the specified class does not have a trivial special member of |
| /// the given kind. |
| void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) { |
| QualType Ty = Context.getRecordType(RD); |
| |
| bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment); |
| checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM, |
| TSK_CompleteObject, TAH_IgnoreTrivialABI, |
| /*Diagnose*/true); |
| } |
| |
| /// Determine whether a defaulted or deleted special member function is trivial, |
| /// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12, |
| /// C++11 [class.copy]p25, and C++11 [class.dtor]p5. |
| bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, |
| TrivialABIHandling TAH, bool Diagnose) { |
| assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough"); |
| |
| CXXRecordDecl *RD = MD->getParent(); |
| |
| bool ConstArg = false; |
| |
| // C++11 [class.copy]p12, p25: [DR1593] |
| // A [special member] is trivial if [...] its parameter-type-list is |
| // equivalent to the parameter-type-list of an implicit declaration [...] |
| switch (CSM) { |
| case CXXDefaultConstructor: |
| case CXXDestructor: |
| // Trivial default constructors and destructors cannot have parameters. |
| break; |
| |
| case CXXCopyConstructor: |
| case CXXCopyAssignment: { |
| // Trivial copy operations always have const, non-volatile parameter types. |
| ConstArg = true; |
| const ParmVarDecl *Param0 = MD->getParamDecl(0); |
| const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>(); |
| if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) { |
| if (Diagnose) |
| Diag(Param0->getLocation(), diag::note_nontrivial_param_type) |
| << Param0->getSourceRange() << Param0->getType() |
| << Context.getLValueReferenceType( |
| Context.getRecordType(RD).withConst()); |
| return false; |
| } |
| break; |
| } |
| |
| case CXXMoveConstructor: |
| case CXXMoveAssignment: { |
| // Trivial move operations always have non-cv-qualified parameters. |
| const ParmVarDecl *Param0 = MD->getParamDecl(0); |
| const RValueReferenceType *RT = |
| Param0->getType()->getAs<RValueReferenceType>(); |
| if (!RT || RT->getPointeeType().getCVRQualifiers()) { |
| if (Diagnose) |
| Diag(Param0->getLocation(), diag::note_nontrivial_param_type) |
| << Param0->getSourceRange() << Param0->getType() |
| << Context.getRValueReferenceType(Context.getRecordType(RD)); |
| return false; |
| } |
| break; |
| } |
| |
| case CXXInvalid: |
| llvm_unreachable("not a special member"); |
| } |
| |
| if (MD->getMinRequiredArguments() < MD->getNumParams()) { |
| if (Diagnose) |
| Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(), |
| diag::note_nontrivial_default_arg) |
| << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange(); |
| return false; |
| } |
| if (MD->isVariadic()) { |
| if (Diagnose) |
| Diag(MD->getLocation(), diag::note_nontrivial_variadic); |
| return false; |
| } |
| |
| // C++11 [class.ctor]p5, C++11 [class.dtor]p5: |
| // A copy/move [constructor or assignment operator] is trivial if |
| // -- the [member] selected to copy/move each direct base class subobject |
| // is trivial |
| // |
| // C++11 [class.copy]p12, C++11 [class.copy]p25: |
| // A [default constructor or destructor] is trivial if |
| // -- all the direct base classes have trivial [default constructors or |
| // destructors] |
| for (const auto &BI : RD->bases()) |
| if (!checkTrivialSubobjectCall(*this, BI.getLocStart(), BI.getType(), |
| ConstArg, CSM, TSK_BaseClass, TAH, Diagnose)) |
| return false; |
| |
| // C++11 [class.ctor]p5, C++11 [class.dtor]p5: |
| // A copy/move [constructor or assignment operator] for a class X is |
| // trivial if |
| // -- for each non-static data member of X that is of class type (or array |
| // thereof), the constructor selected to copy/move that member is |
| // trivial |
| // |
| // C++11 [class.copy]p12, C++11 [class.copy]p25: |
| // A [default constructor or destructor] is trivial if |
| // -- for all of the non-static data members of its class that are of class |
| // type (or array thereof), each such class has a trivial [default |
| // constructor or destructor] |
| if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose)) |
| return false; |
| |
| // C++11 [class.dtor]p5: |
| // A destructor is trivial if [...] |
| // -- the destructor is not virtual |
| if (CSM == CXXDestructor && MD->isVirtual()) { |
| if (Diagnose) |
| Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD; |
| return false; |
| } |
| |
| // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25: |
| // A [special member] for class X is trivial if [...] |
| // -- class X has no virtual functions and no virtual base classes |
| if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) { |
| if (!Diagnose) |
| return false; |
| |
| if (RD->getNumVBases()) { |
| // Check for virtual bases. We already know that the corresponding |
| // member in all bases is trivial, so vbases must all be direct. |
| CXXBaseSpecifier &BS = *RD->vbases_begin(); |
| assert(BS.isVirtual()); |
| Diag(BS.getLocStart(), diag::note_nontrivial_has_virtual) << RD << 1; |
| return false; |
| } |
| |
| // Must have a virtual method. |
| for (const auto *MI : RD->methods()) { |
| if (MI->isVirtual()) { |
| SourceLocation MLoc = MI->getLocStart(); |
| Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0; |
| return false; |
| } |
| } |
| |
| llvm_unreachable("dynamic class with no vbases and no virtual functions"); |
| } |
| |
| // Looks like it's trivial! |
| return true; |
| } |
| |
| namespace { |
| struct FindHiddenVirtualMethod { |
| Sema *S; |
| CXXMethodDecl *Method; |
| llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods; |
| SmallVector<CXXMethodDecl *, 8> OverloadedMethods; |
| |
| private: |
| /// Check whether any most overriden method from MD in Methods |
| static bool CheckMostOverridenMethods( |
| const CXXMethodDecl *MD, |
| const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) { |
| if (MD->size_overridden_methods() == 0) |
| return Methods.count(MD->getCanonicalDecl()); |
| for (const CXXMethodDecl *O : MD->overridden_methods()) |
| if (CheckMostOverridenMethods(O, Methods)) |
| return true; |
| return false; |
| } |
| |
| public: |
| /// Member lookup function that determines whether a given C++ |
| /// method overloads virtual methods in a base class without overriding any, |
| /// to be used with CXXRecordDecl::lookupInBases(). |
| bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { |
| RecordDecl *BaseRecord = |
| Specifier->getType()->getAs<RecordType>()->getDecl(); |
| |
| DeclarationName Name = Method->getDeclName(); |
| assert(Name.getNameKind() == DeclarationName::Identifier); |
| |
| bool foundSameNameMethod = false; |
| SmallVector<CXXMethodDecl *, 8> overloadedMethods; |
| for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty(); |
| Path.Decls = Path.Decls.slice(1)) { |
| NamedDecl *D = Path.Decls.front(); |
| if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { |
| MD = MD->getCanonicalDecl(); |
| foundSameNameMethod = true; |
| // Interested only in hidden virtual methods. |
| if (!MD->isVirtual()) |
| continue; |
| // If the method we are checking overrides a method from its base |
| // don't warn about the other overloaded methods. Clang deviates from |
| // GCC by only diagnosing overloads of inherited virtual functions that |
| // do not override any other virtual functions in the base. GCC's |
| // -Woverloaded-virtual diagnoses any derived function hiding a virtual |
| // function from a base class. These cases may be better served by a |
| // warning (not specific to virtual functions) on call sites when the |
| // call would select a different function from the base class, were it |
| // visible. |
| // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example. |
| if (!S->IsOverload(Method, MD, false)) |
| return true; |
| // Collect the overload only if its hidden. |
| if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods)) |
| overloadedMethods.push_back(MD); |
| } |
| } |
| |
| if (foundSameNameMethod) |
| OverloadedMethods.append(overloadedMethods.begin(), |
| overloadedMethods.end()); |
| return foundSameNameMethod; |
| } |
| }; |
| } // end anonymous namespace |
| |
| /// Add the most overriden methods from MD to Methods |
| static void AddMostOverridenMethods(const CXXMethodDecl *MD, |
| llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) { |
| if (MD->size_overridden_methods() == 0) |
| Methods.insert(MD->getCanonicalDecl()); |
| else |
| for (const CXXMethodDecl *O : MD->overridden_methods()) |
| AddMostOverridenMethods(O, Methods); |
| } |
| |
| /// Check if a method overloads virtual methods in a base class without |
| /// overriding any. |
| void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD, |
| SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { |
| if (!MD->getDeclName().isIdentifier()) |
| return; |
| |
| CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases. |
| /*bool RecordPaths=*/false, |
| /*bool DetectVirtual=*/false); |
| FindHiddenVirtualMethod FHVM; |
| FHVM.Method = MD; |
| FHVM.S = this; |
| |
| // Keep the base methods that were overriden or introduced in the subclass |
| // by 'using' in a set. A base method not in this set is hidden. |
| CXXRecordDecl *DC = MD->getParent(); |
| DeclContext::lookup_result R = DC->lookup(MD->getDeclName()); |
| for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { |
| NamedDecl *ND = *I; |
| if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I)) |
| ND = shad->getTargetDecl(); |
| if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND)) |
| AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods); |
| } |
| |
| if (DC->lookupInBases(FHVM, Paths)) |
| OverloadedMethods = FHVM.OverloadedMethods; |
| } |
| |
| void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD, |
| SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) { |
| for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) { |
| CXXMethodDecl *overloadedMD = OverloadedMethods[i]; |
| PartialDiagnostic PD = PDiag( |
| diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD; |
| HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType()); |
| Diag(overloadedMD->getLocation(), PD); |
| } |
| } |
| |
| /// Diagnose methods which overload virtual methods in a base class |
| /// without overriding any. |
| void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) { |
| if (MD->isInvalidDecl()) |
| return; |
| |
| if (Diags.isIgnored(diag::warn_overloaded_virtual, MD->getLocation())) |
| return; |
| |
| SmallVector<CXXMethodDecl *, 8> OverloadedMethods; |
| FindHiddenVirtualMethods(MD, OverloadedMethods); |
| if (!OverloadedMethods.empty()) { |
| Diag(MD->getLocation(), diag::warn_overloaded_virtual) |
| << MD << (OverloadedMethods.size() > 1); |
| |
| NoteHiddenVirtualMethods(MD, OverloadedMethods); |
| } |
| } |
| |
| void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { |
| auto PrintDiagAndRemoveAttr = [&]() { |
| // No diagnostics if this is a template instantiation. |
| if (!isTemplateInstantiation(RD.getTemplateSpecializationKind())) |
| Diag(RD.getAttr<TrivialABIAttr>()->getLocation(), |
| diag::ext_cannot_use_trivial_abi) << &RD; |
| RD.dropAttr<TrivialABIAttr>(); |
| }; |
| |
| // Ill-formed if the struct has virtual functions. |
| if (RD.isPolymorphic()) { |
| PrintDiagAndRemoveAttr(); |
| return; |
| } |
| |
| for (const auto &B : RD.bases()) { |
| // Ill-formed if the base class is non-trivial for the purpose of calls or a |
| // virtual base. |
| if ((!B.getType()->isDependentType() && |
| !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) || |
| B.isVirtual()) { |
| PrintDiagAndRemoveAttr(); |
| return; |
| } |
| } |
| |
| for (const auto *FD : RD.fields()) { |
| // Ill-formed if the field is an ObjectiveC pointer or of a type that is |
| // non-trivial for the purpose of calls. |
| QualType FT = FD->getType(); |
| if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) { |
| PrintDiagAndRemoveAttr(); |
| return; |
| } |
| |
| if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>()) |
| if (!RT->isDependentType() && |
| !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) { |
| PrintDiagAndRemoveAttr(); |
| return; |
| } |
| } |
| } |
| |
| void Sema::ActOnFinishCXXMemberSpecification( |
| Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, |
| SourceLocation RBrac, const ParsedAttributesView &AttrList) { |
| if (!TagDecl) |
| return; |
| |
| AdjustDeclIfTemplate(TagDecl); |
| |
| for (const ParsedAttr &AL : AttrList) { |
| if (AL.getKind() != ParsedAttr::AT_Visibility) |
| continue; |
| AL.setInvalid(); |
| Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) |
| << AL.getName(); |
| } |
| |
| ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( |
| // strict aliasing violation! |
| reinterpret_cast<Decl**>(FieldCollector->getCurFields()), |
| FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList); |
| |
| CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl)); |
| } |
| |
| /// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared |
| /// special functions, such as the default constructor, copy |
| /// constructor, or destructor, to the given C++ class (C++ |
| /// [special]p1). This routine can only be executed just before the |
| /// definition of the class is complete. |
| void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { |
| if (ClassDecl->needsImplicitDefaultConstructor()) { |
| ++ASTContext::NumImplicitDefaultConstructors; |
| |
| if (ClassDecl->hasInheritedConstructor()) |
| DeclareImplicitDefaultConstructor(ClassDecl); |
| } |
| |
| if (ClassDecl->needsImplicitCopyConstructor()) { |
| ++ASTContext::NumImplicitCopyConstructors; |
| |
| // If the properties or semantics of the copy constructor couldn't be |
| // determined while the class was being declared, force a declaration |
| // of it now. |
| if (ClassDecl->needsOverloadResolutionForCopyConstructor() || |
| ClassDecl->hasInheritedConstructor()) |
| DeclareImplicitCopyConstructor(ClassDecl); |
| // For the MS ABI we need to know whether the copy ctor is deleted. A |
| // prerequisite for deleting the implicit copy ctor is that the class has a |
| // move ctor or move assignment that is either user-declared or whose |
| // semantics are inherited from a subobject. FIXME: We should provide a more |
| // direct way for CodeGen to ask whether the constructor was deleted. |
| else if (Context.getTargetInfo().getCXXABI().isMicrosoft() && |
| (ClassDecl->hasUserDeclaredMoveConstructor() || |
| ClassDecl->needsOverloadResolutionForMoveConstructor() || |
| ClassDecl->hasUserDeclaredMoveAssignment() || |
| ClassDecl->needsOverloadResolutionForMoveAssignment())) |
| DeclareImplicitCopyConstructor(ClassDecl); |
| } |
| |
| if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) { |
| ++ASTContext::NumImplicitMoveConstructors; |
| |
| if (ClassDecl->needsOverloadResolutionForMoveConstructor() || |
| ClassDecl->hasInheritedConstructor()) |
| DeclareImplicitMoveConstructor(ClassDecl); |
| } |
| |
| if (ClassDecl->needsImplicitCopyAssignment()) { |
| ++ASTContext::NumImplicitCopyAssignmentOperators; |
| |
| // If we have a dynamic class, then the copy assignment operator may be |
| // virtual, so we have to declare it immediately. This ensures that, e.g., |
| // it shows up in the right place in the vtable and that we diagnose |
| // problems with the implicit exception specification. |
| if (ClassDecl->isDynamicClass() || |
| ClassDecl->needsOverloadResolutionForCopyAssignment() || |
| ClassDecl->hasInheritedAssignment()) |
| DeclareImplicitCopyAssignment(ClassDecl); |
| } |
| |
| if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) { |
| ++ASTContext::NumImplicitMoveAssignmentOperators; |
| |
| // Likewise for the move assignment operator. |
| if (ClassDecl->isDynamicClass() || |
| ClassDecl->needsOverloadResolutionForMoveAssignment() || |
| ClassDecl->hasInheritedAssignment()) |
| DeclareImplicitMoveAssignment(ClassDecl); |
| } |
| |
| if (ClassDecl->needsImplicitDestructor()) { |
| ++ASTContext::NumImplicitDestructors; |
| |
| // If we have a dynamic class, then the destructor may be virtual, so we |
| // have to declare the destructor immediately. This ensures that, e.g., it |
| // shows up in the right place in the vtable and that we diagnose problems |
| // with the implicit exception specification. |
| if (ClassDecl->isDynamicClass() || |
| ClassDecl->needsOverloadResolutionForDestructor()) |
| DeclareImplicitDestructor(ClassDecl); |
| } |
| } |
| |
| unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) { |
| if (!D) |
| return 0; |
| |
| // The order of template parameters is not important here. All names |
| // get added to the same scope. |
| SmallVector<TemplateParameterList *, 4> ParameterLists; |
| |
| if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) |
| D = TD->getTemplatedDecl(); |
| |
| if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) |
| ParameterLists.push_back(PSD->getTemplateParameters()); |
| |
| if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) { |
| for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i) |
| ParameterLists.push_back(DD->getTemplateParameterList(i)); |
| |
| if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) |
| ParameterLists.push_back(FTD->getTemplateParameters()); |
| } |
| } |
| |
| if (TagDecl *TD = dyn_cast<TagDecl>(D)) { |
| for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i) |
| ParameterLists.push_back(TD->getTemplateParameterList(i)); |
| |
| if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) { |
| if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) |
| ParameterLists.push_back(CTD->getTemplateParameters()); |
| } |
| } |
| |
| unsigned Count = 0; |
| for (TemplateParameterList *Params : ParameterLists) { |
| if (Params->size() > 0) |
| // Ignore explicit specializations; they don't contribute to the template |
| // depth. |
| ++Count; |
| for (NamedDecl *Param : *Params) { |
| if (Param->getDeclName()) { |
| S->AddDecl(Param); |
| IdResolver.AddDecl(Param); |
| } |
| } |
| } |
| |
| return Count; |
| } |
| |
| void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) { |
| if (!RecordD) return; |
| AdjustDeclIfTemplate(RecordD); |
| CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD); |
| PushDeclContext(S, Record); |
| } |
| |
| void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) { |
| if (!RecordD) return; |
| PopDeclContext(); |
| } |
| |
| /// This is used to implement the constant expression evaluation part of the |
| /// attribute enable_if extension. There is nothing in standard C++ which would |
| /// require reentering parameters. |
| void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) { |
| if (!Param) |
| return; |
| |
| S->AddDecl(Param); |
| if (Param->getDeclName()) |
| IdResolver.AddDecl(Param); |
| } |
| |
| /// ActOnStartDelayedCXXMethodDeclaration - We have completed |
| /// parsing a top-level (non-nested) C++ class, and we are now |
| /// parsing those parts of the given Method declaration that could |
| /// not be parsed earlier (C++ [class.mem]p2), such as default |
| /// arguments. This action should enter the scope of the given |
| /// Method declaration as if we had just parsed the qualified method |
| /// name. However, it should not bring the parameters into scope; |
| /// that will be performed by ActOnDelayedCXXMethodParameter. |
| void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { |
| } |
| |
| /// ActOnDelayedCXXMethodParameter - We've already started a delayed |
| /// C++ method declaration. We're (re-)introducing the given |
| /// function parameter into scope for use in parsing later parts of |
| /// the method declaration. For example, we could see an |
| /// ActOnParamDefaultArgument event for this parameter. |
| void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) { |
| if (!ParamD) |
| return; |
| |
| ParmVarDecl *Param = cast<ParmVarDecl>(ParamD); |
| |
| // If this parameter has an unparsed default argument, clear it out |
| // to make way for the parsed default argument. |
| if (Param->hasUnparsedDefaultArg()) |
| Param->setDefaultArg(nullptr); |
| |
| S->AddDecl(Param); |
| if (Param->getDeclName()) |
| IdResolver.AddDecl(Param); |
| } |
| |
| /// ActOnFinishDelayedCXXMethodDeclaration - We have finished |
| /// processing the delayed method declaration for Method. The method |
| /// declaration is now considered finished. There may be a separate |
| /// ActOnStartOfFunctionDef action later (not necessarily |
| /// immediately!) for this method, if it was also defined inside the |
| /// class body. |
| void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { |
| if (!MethodD) |
| return; |
| |
| AdjustDeclIfTemplate(MethodD); |
| |
| FunctionDecl *Method = cast<FunctionDecl>(MethodD); |
| |
| // Now that we have our default arguments, check the constructor |
| // again. It could produce additional diagnostics or affect whether |
| // the class has implicitly-declared destructors, among other |
| // things. |
| if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method)) |
| CheckConstructor(Constructor); |
| |
| // Check the default arguments, which we may have added. |
| if (!Method->isInvalidDecl()) |
| CheckCXXDefaultArguments(Method); |
| } |
| |
| /// CheckConstructorDeclarator - Called by ActOnDeclarator to check |
| /// the well-formedness of the constructor declarator @p D with type @p |
| /// R. If there are any errors in the declarator, this routine will |
| /// emit diagnostics and set the invalid bit to true. In any case, the type |
| /// will be updated to reflect a well-formed type for the constructor and |
| /// returned. |
| QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, |
| StorageClass &SC) { |
| bool isVirtual = D.getDeclSpec().isVirtualSpecified(); |
| |
| // C++ [class.ctor]p3: |
| // A constructor shall not be virtual (10.3) or static (9.4). A |
| // constructor can be invoked for a const, volatile or const |
| // volatile object. A constructor shall not be declared const, |
| // volatile, or const volatile (9.3.2). |
| if (isVirtual) { |
| if (!D.isInvalidType()) |
| Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) |
| << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc()) |
| << SourceRange(D.getIdentifierLoc()); |
| D.setInvalidType(); |
| } |
| if (SC == SC_Static) { |
| if (!D.isInvalidType()) |
| Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be) |
| << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) |
| << SourceRange(D.getIdentifierLoc()); |
| D.setInvalidType(); |
| SC = SC_None; |
| } |
| |
| if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) { |
| diagnoseIgnoredQualifiers( |
| diag::err_constructor_return_type, TypeQuals, SourceLocation(), |
| D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(), |
| D.getDeclSpec().getRestrictSpecLoc(), |
| D.getDeclSpec().getAtomicSpecLoc()); |
| D.setInvalidType(); |
| } |
| |
| DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); |
| if (FTI.TypeQuals != 0) { |
| if (FTI.TypeQuals & Qualifiers::Const) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) |
| << "const" << SourceRange(D.getIdentifierLoc()); |
| if (FTI.TypeQuals & Qualifiers::Volatile) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) |
| << "volatile" << SourceRange(D.getIdentifierLoc()); |
| if (FTI.TypeQuals & Qualifiers::Restrict) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor) |
| << "restrict" << SourceRange(D.getIdentifierLoc()); |
| D.setInvalidType(); |
| } |
| |
| // C++0x [class.ctor]p4: |
| // A constructor shall not be declared with a ref-qualifier. |
| if (FTI.hasRefQualifier()) { |
| Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) |
| << FTI.RefQualifierIsLValueRef |
| << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); |
| D.setInvalidType(); |
| } |
| |
| // Rebuild the function type "R" without any type qualifiers (in |
| // case any of the errors above fired) and with "void" as the |
| // return type, since constructors don't have return types. |
| const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); |
| if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType()) |
| return R; |
| |
| FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); |
| EPI.TypeQuals = 0; |
| EPI.RefQualifier = RQ_None; |
| |
| return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI); |
| } |
| |
| /// CheckConstructor - Checks a fully-formed constructor for |
| /// well-formedness, issuing any diagnostics required. Returns true if |
| /// the constructor declarator is invalid. |
| void Sema::CheckConstructor(CXXConstructorDecl *Constructor) { |
| CXXRecordDecl *ClassDecl |
| = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext()); |
| if (!ClassDecl) |
| return Constructor->setInvalidDecl(); |
| |
| // C++ [class.copy]p3: |
| // A declaration of a constructor for a class X is ill-formed if |
| // its first parameter is of type (optionally cv-qualified) X and |
| // either there are no other parameters or else all other |
| // parameters have default arguments. |
| if (!Constructor->isInvalidDecl() && |
| ((Constructor->getNumParams() == 1) || |
| (Constructor->getNumParams() > 1 && |
| Constructor->getParamDecl(1)->hasDefaultArg())) && |
| Constructor->getTemplateSpecializationKind() |
| != TSK_ImplicitInstantiation) { |
| QualType ParamType = Constructor->getParamDecl(0)->getType(); |
| QualType ClassTy = Context.getTagDeclType(ClassDecl); |
| if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) { |
| SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation(); |
| const char *ConstRef |
| = Constructor->getParamDecl(0)->getIdentifier() ? "const &" |
| : " const &"; |
| Diag(ParamLoc, diag::err_constructor_byvalue_arg) |
| << FixItHint::CreateInsertion(ParamLoc, ConstRef); |
| |
| // FIXME: Rather that making the constructor invalid, we should endeavor |
| // to fix the type. |
| Constructor->setInvalidDecl(); |
| } |
| } |
| } |
| |
| /// CheckDestructor - Checks a fully-formed destructor definition for |
| /// well-formedness, issuing any diagnostics required. Returns true |
| /// on error. |
| bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { |
| CXXRecordDecl *RD = Destructor->getParent(); |
| |
| if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) { |
| SourceLocation Loc; |
| |
| if (!Destructor->isImplicit()) |
| Loc = Destructor->getLocation(); |
| else |
| Loc = RD->getLocation(); |
| |
| // If we have a virtual destructor, look up the deallocation function |
| if (FunctionDecl *OperatorDelete = |
| FindDeallocationFunctionForDestructor(Loc, RD)) { |
| Expr *ThisArg = nullptr; |
| |
| // If the notional 'delete this' expression requires a non-trivial |
| // conversion from 'this' to the type of a destroying operator delete's |
| // first parameter, perform that conversion now. |
| if (OperatorDelete->isDestroyingOperatorDelete()) { |
| QualType ParamType = OperatorDelete->getParamDecl(0)->getType(); |
| if (!declaresSameEntity(ParamType->getAsCXXRecordDecl(), RD)) { |
| // C++ [class.dtor]p13: |
| // ... as if for the expression 'delete this' appearing in a |
| // non-virtual destructor of the destructor's class. |
| ContextRAII SwitchContext(*this, Destructor); |
| ExprResult This = |
| ActOnCXXThis(OperatorDelete->getParamDecl(0)->getLocation()); |
| assert(!This.isInvalid() && "couldn't form 'this' expr in dtor?"); |
| This = PerformImplicitConversion(This.get(), ParamType, AA_Passing); |
| if (This.isInvalid()) { |
| // FIXME: Register this as a context note so that it comes out |
| // in the right order. |
| Diag(Loc, diag::note_implicit_delete_this_in_destructor_here); |
| return true; |
| } |
| ThisArg = This.get(); |
| } |
| } |
| |
| MarkFunctionReferenced(Loc, OperatorDelete); |
| Destructor->setOperatorDelete(OperatorDelete, ThisArg); |
| } |
| } |
| |
| return false; |
| } |
| |
| /// CheckDestructorDeclarator - Called by ActOnDeclarator to check |
| /// the well-formednes of the destructor declarator @p D with type @p |
| /// R. If there are any errors in the declarator, this routine will |
| /// emit diagnostics and set the declarator to invalid. Even if this happens, |
| /// will be updated to reflect a well-formed type for the destructor and |
| /// returned. |
| QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, |
| StorageClass& SC) { |
| // C++ [class.dtor]p1: |
| // [...] A typedef-name that names a class is a class-name |
| // (7.1.3); however, a typedef-name that names a class shall not |
| // be used as the identifier in the declarator for a destructor |
| // declaration. |
| QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); |
| if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>()) |
| Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) |
| << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl()); |
| else if (const TemplateSpecializationType *TST = |
| DeclaratorType->getAs<TemplateSpecializationType>()) |
| if (TST->isTypeAlias()) |
| Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) |
| << DeclaratorType << 1; |
| |
| // C++ [class.dtor]p2: |
| // A destructor is used to destroy objects of its class type. A |
| // destructor takes no parameters, and no return type can be |
| // specified for it (not even void). The address of a destructor |
| // shall not be taken. A destructor shall not be static. A |
| // destructor can be invoked for a const, volatile or const |
| // volatile object. A destructor shall not be declared const, |
| // volatile or const volatile (9.3.2). |
| if (SC == SC_Static) { |
| if (!D.isInvalidType()) |
| Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be) |
| << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) |
| << SourceRange(D.getIdentifierLoc()) |
| << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc()); |
| |
| SC = SC_None; |
| } |
| if (!D.isInvalidType()) { |
| // Destructors don't have return types, but the parser will |
| // happily parse something like: |
| // |
| // class X { |
| // float ~X(); |
| // }; |
| // |
| // The return type will be eliminated later. |
| if (D.getDeclSpec().hasTypeSpecifier()) |
| Diag(D.getIdentifierLoc(), diag::err_destructor_return_type) |
| << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc()) |
| << SourceRange(D.getIdentifierLoc()); |
| else if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) { |
| diagnoseIgnoredQualifiers(diag::err_destructor_return_type, TypeQuals, |
| SourceLocation(), |
| D.getDeclSpec().getConstSpecLoc(), |
| D.getDeclSpec().getVolatileSpecLoc(), |
| D.getDeclSpec().getRestrictSpecLoc(), |
| D.getDeclSpec().getAtomicSpecLoc()); |
| D.setInvalidType(); |
| } |
| } |
| |
| DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); |
| if (FTI.TypeQuals != 0 && !D.isInvalidType()) { |
| if (FTI.TypeQuals & Qualifiers::Const) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) |
| << "const" << SourceRange(D.getIdentifierLoc()); |
| if (FTI.TypeQuals & Qualifiers::Volatile) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) |
| << "volatile" << SourceRange(D.getIdentifierLoc()); |
| if (FTI.TypeQuals & Qualifiers::Restrict) |
| Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor) |
| << "restrict" << SourceRange(D.getIdentifierLoc()); |
| D.setInvalidType(); |
| } |
| |
| // C++0x [class.dtor]p2: |
| // A destructor shall not be declared with a ref-qualifier. |
| if (FTI.hasRefQualifier()) { |
| Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) |
| << FTI.RefQualifierIsLValueRef |
| << FixItHint::CreateRemoval(FTI.getRefQualifierLoc()); |
| D.setInvalidType(); |
| } |
| |
| // Make sure we don't have any parameters. |
| if (FTIHasNonVoidParameters(FTI)) { |
| Diag(D.getIdentifierLoc(), diag::err_destructor_with_params); |
| |
| // Delete the parameters. |
| FTI.freeParams(); |
| D.setInvalidType(); |
| } |
| |
| // Make sure the destructor isn't variadic. |
| if (FTI.isVariadic) { |
| Diag(D.getIdentifierLoc(), diag::err_destructor_variadic); |
| D.setInvalidType(); |
| } |
| |
| // Rebuild the function type "R" without any type qualifiers or |
| // parameters (in case any of the errors above fired) and with |
| // "void" as the return type, since destructors don't have return |
| // types. |
| if (!D.isInvalidType()) |
| return R; |
| |
| const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); |
| FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); |
| EPI.Variadic = false; |
| EPI.TypeQuals = 0; |
| EPI.RefQualifier = RQ_None; |
| return Context.getFunctionType(Context.VoidTy, None, EPI); |
| } |
| |
| static void extendLeft(SourceRange &R, SourceRange Before) { |
| if (Before.isInvalid()) |
| return; |
| R.setBegin(Before.getBegin()); |
| if (R.getEnd().isInvalid()) |
| R.setEnd(Before.getEnd()); |
| } |
| |
| static void extendRight(SourceRange &R, SourceRange After) { |
| if (After.isInvalid()) |
| return; |
| if (R.getBegin().isInvalid()) |
| R.setBegin(After.getBegin()); |
| R.setEnd(After.getEnd()); |
| } |
| |
| /// CheckConversionDeclarator - Called by ActOnDeclarator to check the |
| /// well-formednes of the conversion function declarator @p D with |
| /// type @p R. If there are any errors in the declarator, this routine |
| /// will emit diagnostics and return true. Otherwise, it will return |
| /// false. Either way, the type @p R will be updated to reflect a |
| /// well-formed type for the conversion operator. |
| void Sema::CheckConversionDeclarator(Declarator &D, QualType &R, |
| StorageClass& SC) { |
| // C++ [class.conv.fct]p1: |
| // Neither parameter types nor return type can be specified. The |
| // type of a conversion function (8.3.5) is "function taking no |
| // parameter returning conversion-type-id." |
| if (SC == SC_Static) { |
| if (!D.isInvalidType()) |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member) |
| << SourceRange(D.getDeclSpec().getStorageClassSpecLoc()) |
| << D.getName().getSourceRange(); |
| D.setInvalidType(); |
| SC = SC_None; |
| } |
| |
| TypeSourceInfo *ConvTSI = nullptr; |
| QualType ConvType = |
| GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI); |
| |
| const DeclSpec &DS = D.getDeclSpec(); |
| if (DS.hasTypeSpecifier() && !D.isInvalidType()) { |
| // Conversion functions don't have return types, but the parser will |
| // happily parse something like: |
| // |
| // class X { |
| // float operator bool(); |
| // }; |
| // |
| // The return type will be changed later anyway. |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type) |
| << SourceRange(DS.getTypeSpecTypeLoc()) |
| << SourceRange(D.getIdentifierLoc()); |
| D.setInvalidType(); |
| } else if (DS.getTypeQualifiers() && !D.isInvalidType()) { |
| // It's also plausible that the user writes type qualifiers in the wrong |
| // place, such as: |
| // struct S { const operator int(); }; |
| // FIXME: we could provide a fixit to move the qualifiers onto the |
| // conversion type. |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl) |
| << SourceRange(D.getIdentifierLoc()) << 0; |
| D.setInvalidType(); |
| } |
| |
| const FunctionProtoType *Proto = R->getAs<FunctionProtoType>(); |
| |
| // Make sure we don't have any parameters. |
| if (Proto->getNumParams() > 0) { |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params); |
| |
| // Delete the parameters. |
| D.getFunctionTypeInfo().freeParams(); |
| D.setInvalidType(); |
| } else if (Proto->isVariadic()) { |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic); |
| D.setInvalidType(); |
| } |
| |
| // Diagnose "&operator bool()" and other such nonsense. This |
| // is actually a gcc extension which we don't support. |
| if (Proto->getReturnType() != ConvType) { |
| bool NeedsTypedef = false; |
| SourceRange Before, After; |
| |
| // Walk the chunks and extract information on them for our diagnostic. |
| bool PastFunctionChunk = false; |
| for (auto &Chunk : D.type_objects()) { |
| switch (Chunk.Kind) { |
| case DeclaratorChunk::Function: |
| if (!PastFunctionChunk) { |
| if (Chunk.Fun.HasTrailingReturnType) { |
| TypeSourceInfo *TRT = nullptr; |
| GetTypeFromParser(Chunk.Fun.getTrailingReturnType(), &TRT); |
| if (TRT) extendRight(After, TRT->getTypeLoc().getSourceRange()); |
| } |
| PastFunctionChunk = true; |
| break; |
| } |
| LLVM_FALLTHROUGH; |
| case DeclaratorChunk::Array: |
| NeedsTypedef = true; |
| extendRight(After, Chunk.getSourceRange()); |
| break; |
| |
| case DeclaratorChunk::Pointer: |
| case DeclaratorChunk::BlockPointer: |
| case DeclaratorChunk::Reference: |
| case DeclaratorChunk::MemberPointer: |
| case DeclaratorChunk::Pipe: |
| extendLeft(Before, Chunk.getSourceRange()); |
| break; |
| |
| case DeclaratorChunk::Paren: |
| extendLeft(Before, Chunk.Loc); |
| extendRight(After, Chunk.EndLoc); |
| break; |
| } |
| } |
| |
| SourceLocation Loc = Before.isValid() ? Before.getBegin() : |
| After.isValid() ? After.getBegin() : |
| D.getIdentifierLoc(); |
| auto &&DB = Diag(Loc, diag::err_conv_function_with_complex_decl); |
| DB << Before << After; |
| |
| if (!NeedsTypedef) { |
| DB << /*don't need a typedef*/0; |
| |
| // If we can provide a correct fix-it hint, do so. |
| if (After.isInvalid() && ConvTSI) { |
| SourceLocation InsertLoc = |
| getLocForEndOfToken(ConvTSI->getTypeLoc().getLocEnd()); |
| DB << FixItHint::CreateInsertion(InsertLoc, " ") |
| << FixItHint::CreateInsertionFromRange( |
| InsertLoc, CharSourceRange::getTokenRange(Before)) |
| << FixItHint::CreateRemoval(Before); |
| } |
| } else if (!Proto->getReturnType()->isDependentType()) { |
| DB << /*typedef*/1 << Proto->getReturnType(); |
| } else if (getLangOpts().CPlusPlus11) { |
| DB << /*alias template*/2 << Proto->getReturnType(); |
| } else { |
| DB << /*might not be fixable*/3; |
| } |
| |
| // Recover by incorporating the other type chunks into the result type. |
| // Note, this does *not* change the name of the function. This is compatible |
| // with the GCC extension: |
| // struct S { &operator int(); } s; |
| // int &r = s.operator int(); // ok in GCC |
| // S::operator int&() {} // error in GCC, function name is 'operator int'. |
| ConvType = Proto->getReturnType(); |
| } |
| |
| // C++ [class.conv.fct]p4: |
| // The conversion-type-id shall not represent a function type nor |
| // an array type. |
| if (ConvType->isArrayType()) { |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array); |
| ConvType = Context.getPointerType(ConvType); |
| D.setInvalidType(); |
| } else if (ConvType->isFunctionType()) { |
| Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function); |
| ConvType = Context.getPointerType(ConvType); |
| D.setInvalidType(); |
| } |
| |
| // Rebuild the function type "R" without any parameters (in case any |
| // of the errors above fired) and with the conversion type as the |
| // return type. |
| if (D.isInvalidType()) |
| R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo()); |
| |
| // C++0x explicit conversion operators. |
| if (DS.isExplicitSpecified()) |
| Diag(DS.getExplicitSpecLoc(), |
| getLangOpts().CPlusPlus11 |
| ? diag::warn_cxx98_compat_explicit_conversion_functions |
| : diag::ext_explicit_conversion_functions) |
| << SourceRange(DS.getExplicitSpecLoc()); |
| } |
| |
| /// ActOnConversionDeclarator - Called by ActOnDeclarator to complete |
| /// the declaration of the given C++ conversion function. This routine |
| /// is responsible for recording the conversion function in the C++ |
| /// class, if possible. |
| Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) { |
| assert(Conversion && "Expected to receive a conversion function declaration"); |
| |
| CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext()); |
| |
| // Make sure we aren't redeclaring the conversion function. |
| QualType ConvType = Context.getCanonicalType(Conversion->getConversionType()); |
| |
| // C++ [class.conv.fct]p1: |
| // [...] A conversion function is never used to convert a |
| // (possibly cv-qualified) object to the (possibly cv-qualified) |
| // same object type (or a reference to it), to a (possibly |
| // cv-qualified) base class of that type (or a reference to it), |
| // or to (possibly cv-qualified) void. |
| // FIXME: Suppress this warning if the conversion function ends up being a |
| // virtual function that overrides a virtual function in a base class. |
| QualType ClassType |
| = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); |
| if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>()) |
| ConvType = ConvTypeRef->getPointeeType(); |
| if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared && |
| Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) |
| /* Suppress diagnostics for instantiations. */; |
| else if (ConvType->isRecordType()) { |
| ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType(); |
| if (ConvType == ClassType) |
| Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used) |
| << ClassType; |
| else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType)) |
| Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used) |
| << ClassType << ConvType; |
| } else if (ConvType->isVoidType()) { |
| Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used) |
| << ClassType << ConvType; |
| } |
| |
| if (FunctionTemplateDecl *ConversionTemplate |
| = Conversion->getDescribedFunctionTemplate()) |
| return ConversionTemplate; |
| |
| return Conversion; |
| } |
| |
| namespace { |
| /// Utility class to accumulate and print a diagnostic listing the invalid |
| /// specifier(s) on a declaration. |
| struct BadSpecifierDiagnoser { |
| BadSpecifierDiagnoser(Sema &S, SourceLocation Loc, unsigned DiagID) |
| : S(S), Diagnostic(S.Diag(Loc, DiagID)) {} |
| ~BadSpecifierDiagnoser() { |
| Diagnostic << Specifiers; |
| } |
| |
| template<typename T> void check(SourceLocation SpecLoc, T Spec) { |
| return check(SpecLoc, DeclSpec::getSpecifierName(Spec)); |
| } |
| void check(SourceLocation SpecLoc, DeclSpec::TST Spec) { |
| return check(SpecLoc, |
| DeclSpec::getSpecifierName(Spec, S.getPrintingPolicy())); |
| } |
| void check(SourceLocation SpecLoc, const char *Spec) { |
| if (SpecLoc.isInvalid()) return; |
| Diagnostic << SourceRange(SpecLoc, SpecLoc); |
| if (!Specifiers.empty()) Specifiers += " "; |
| Specifiers += Spec; |
| } |
| |
| Sema &S; |
| Sema::SemaDiagnosticBuilder Diagnostic; |
| std::string Specifiers; |
| }; |
| } |
| |
| /// Check the validity of a declarator that we parsed for a deduction-guide. |
| /// These aren't actually declarators in the grammar, so we need to check that |
| /// the user didn't specify any pieces that are not part of the deduction-guide |
| /// grammar. |
| void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, |
| StorageClass &SC) { |
| TemplateName GuidedTemplate = D.getName().TemplateName.get().get(); |
| TemplateDecl *GuidedTemplateDecl = GuidedTemplate.getAsTemplateDecl(); |
| assert(GuidedTemplateDecl && "missing template decl for deduction guide"); |
| |
| // C++ [temp.deduct.guide]p3: |
| // A deduction-gide shall be declared in the same scope as the |
| // corresponding class template. |
| if (!CurContext->getRedeclContext()->Equals( |
| GuidedTemplateDecl->getDeclContext()->getRedeclContext())) { |
| Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope) |
| << GuidedTemplateDecl; |
| Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here); |
| } |
| |
| auto &DS = D.getMutableDeclSpec(); |
| // We leave 'friend' and 'virtual' to be rejected in the normal way. |
| if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() || |
| DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() || |
| DS.isNoreturnSpecified() || DS.isConstexprSpecified()) { |
| BadSpecifierDiagnoser Diagnoser( |
| *this, D.getIdentifierLoc(), |
| diag::err_deduction_guide_invalid_specifier); |
| |
| Diagnoser.check(DS.getStorageClassSpecLoc(), DS.getStorageClassSpec()); |
| DS.ClearStorageClassSpecs(); |
| SC = SC_None; |
| |
| // 'explicit' is permitted. |
| Diagnoser.check(DS.getInlineSpecLoc(), "inline"); |
| Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn"); |
| Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr"); |
| DS.ClearConstexprSpec(); |
| |
| Diagnoser.check(DS.getConstSpecLoc(), "const"); |
| Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict"); |
| Diagnoser.check(DS.getVolatileSpecLoc(), "volatile"); |
| Diagnoser.check(DS.getAtomicSpecLoc(), "_Atomic"); |
| Diagnoser.check(DS.getUnalignedSpecLoc(), "__unaligned"); |
| DS.ClearTypeQualifiers(); |
| |
| Diagnoser.check(DS.getTypeSpecComplexLoc(), DS.getTypeSpecComplex()); |
| Diagnoser.check(DS.getTypeSpecSignLoc(), DS.getTypeSpecSign()); |
| Diagnoser.check(DS.getTypeSpecWidthLoc(), DS.getTypeSpecWidth()); |
| Diagnoser.check(DS.getTypeSpecTypeLoc(), DS.getTypeSpecType()); |
| DS.ClearTypeSpecType(); |
| } |
| |
| if (D.isInvalidType()) |
| return; |
| |
| // Check the declarator is simple enough. |
| bool FoundFunction = false; |
| for (const DeclaratorChunk &Chunk : llvm::reverse(D.type_objects())) { |
| if (Chunk.Kind == DeclaratorChunk::Paren) |
| continue; |
| if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) { |
| Diag(D.getDeclSpec().getLocStart(), |
| diag::err_deduction_guide_with_complex_decl) |
| << D.getSourceRange(); |
| break; |
| } |
| if (!Chunk.Fun.hasTrailingReturnType()) { |
| Diag(D.getName().getLocStart(), |
| diag::err_deduction_guide_no_trailing_return_type); |
| break; |
| } |
| |
| // Check that the return type is written as a specialization of |
| // the template specified as the deduction-guide's name. |
| ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType(); |
| TypeSourceInfo *TSI = nullptr; |
| QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI); |
| assert(TSI && "deduction guide has valid type but invalid return type?"); |
| bool AcceptableReturnType = false; |
| bool MightInstantiateToSpecialization = false; |
| if (auto RetTST = |
| TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>()) { |
| TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName(); |
| bool TemplateMatches = |
| Context.hasSameTemplateName(SpecifiedName, GuidedTemplate); |
| if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches) |
| AcceptableReturnType = true; |
| else { |
| // This could still instantiate to the right type, unless we know it |
| // names the wrong class template. |
| auto *TD = SpecifiedName.getAsTemplateDecl(); |
| MightInstantiateToSpecialization = !(TD && isa<ClassTemplateDecl>(TD) && |
| !TemplateMatches); |
| } |
| } else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) { |
| MightInstantiateToSpecialization = true; |
| } |
| |
| if (!AcceptableReturnType) { |
| Diag(TSI->getTypeLoc().getLocStart(), |
| diag::err_deduction_guide_bad_trailing_return_type) |
| << GuidedTemplate << TSI->getType() << MightInstantiateToSpecialization |
| << TSI->getTypeLoc().getSourceRange(); |
| } |
| |
| // Keep going to check that we don't have any inner declarator pieces (we |
| // could still have a function returning a pointer to a function). |
| FoundFunction = true; |
| } |
| |
| if (D.isFunctionDefinition()) |
| Diag(D.getIdentifierLoc(), diag::err_deduction_guide_defines_function); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Namespace Handling |
| //===----------------------------------------------------------------------===// |
| |
| /// Diagnose a mismatch in 'inline' qualifiers when a namespace is |
| /// reopened. |
| static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, |
| SourceLocation Loc, |
| IdentifierInfo *II, bool *IsInline, |
| NamespaceDecl *PrevNS) { |
| assert(*IsInline != PrevNS->isInline()); |
| |
| // HACK: Work around a bug in libstdc++4.6's <atomic>, where |
| // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as |
| // inline namespaces, with the intention of bringing names into namespace std. |
| // |
| // We support this just well enough to get that case working; this is not |
| // sufficient to support reopening namespaces as inline in general. |
| if (*IsInline && II && II->getName().startswith("__atomic") && |
| S.getSourceManager().isInSystemHeader(Loc)) { |
| // Mark all prior declarations of the namespace as inline. |
| for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS; |
| NS = NS->getPreviousDecl()) |
| NS->setInline(*IsInline); |
| // Patch up the lookup table for the containing namespace. This isn't really |
| // correct, but it's good enough for this particular case. |
| for (auto *I : PrevNS->decls()) |
| if (auto *ND = dyn_cast<NamedDecl>(I)) |
| PrevNS->getParent()->makeDeclVisibleInContext(ND); |
| return; |
| } |
| |
| if (PrevNS->isInline()) |
| // The user probably just forgot the 'inline', so suggest that it |
| // be added back. |
| S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline) |
| << FixItHint::CreateInsertion(KeywordLoc, "inline "); |
| else |
| S.Diag(Loc, diag::err_inline_namespace_mismatch); |
| |
| S.Diag(PrevNS->getLocation(), diag::note_previous_definition); |
| *IsInline = PrevNS->isInline(); |
| } |
| |
| /// ActOnStartNamespaceDef - This is called at the start of a namespace |
| /// definition. |
| Decl *Sema::ActOnStartNamespaceDef( |
| Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, |
| SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, |
| const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { |
| SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; |
| // For anonymous namespace, take the location of the left brace. |
| SourceLocation Loc = II ? IdentLoc : LBrace; |
| bool IsInline = InlineLoc.isValid(); |
| bool IsInvalid = false; |
| bool IsStd = false; |
| bool AddToKnown = false; |
| Scope *DeclRegionScope = NamespcScope->getParent(); |
| |
| NamespaceDecl *PrevNS = nullptr; |
| if (II) { |
| // C++ [namespace.def]p2: |
| // The identifier in an original-namespace-definition shall not |
| // have been previously defined in the declarative region in |
| // which the original-namespace-definition appears. The |
| // identifier in an original-namespace-definition is the name of |
| // the namespace. Subsequently in that declarative region, it is |
| // treated as an original-namespace-name. |
| // |
| // Since namespace names are unique in their scope, and we don't |
| // look through using directives, just look for any ordinary names |
| // as if by qualified name lookup. |
| LookupResult R(*this, II, IdentLoc, LookupOrdinaryName, |
| ForExternalRedeclaration); |
| LookupQualifiedName(R, CurContext->getRedeclContext()); |
| NamedDecl *PrevDecl = |
| R.isSingleResult() ? R.getRepresentativeDecl() : nullptr; |
| PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl); |
| |
| if (PrevNS) { |
| // This is an extended namespace definition. |
| if (IsInline != PrevNS->isInline()) |
| DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II, |
| &IsInline, PrevNS); |
| } else if (PrevDecl) { |
| // This is an invalid name redefinition. |
| Diag(Loc, diag::err_redefinition_different_kind) |
| << II; |
| Diag(PrevDecl->getLocation(), diag::note_previous_definition); |
| IsInvalid = true; |
| // Continue on to push Namespc as current DeclContext and return it. |
| } else if (II->isStr("std") && |
| CurContext->getRedeclContext()->isTranslationUnit()) { |
| // This is the first "real" definition of the namespace "std", so update |
| // our cache of the "std" namespace to point at this definition. |
| PrevNS = getStdNamespace(); |
| IsStd = true; |
| AddToKnown = !IsInline; |
| } else { |
| // We've seen this namespace for the first time. |
| AddToKnown = !IsInline; |
| } |
| } else { |
| // Anonymous namespaces. |
| |
| // Determine whether the parent already has an anonymous namespace. |
| DeclContext *Parent = CurContext->getRedeclContext(); |
| if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { |
| PrevNS = TU->getAnonymousNamespace(); |
| } else { |
| NamespaceDecl *ND = cast<NamespaceDecl>(Parent); |
| PrevNS = ND->getAnonymousNamespace(); |
| } |
| |
| if (PrevNS && IsInline != PrevNS->isInline()) |
| DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II, |
| &IsInline, PrevNS); |
| } |
| |
| NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline, |
| StartLoc, Loc, II, PrevNS); |
| if (IsInvalid) |
| Namespc->setInvalidDecl(); |
| |
| ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList); |
| AddPragmaAttributes(DeclRegionScope, Namespc); |
| |
| // FIXME: Should we be merging attributes? |
| if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>()) |
| PushNamespaceVisibilityAttr(Attr, Loc); |
| |
| if (IsStd) |
| StdNamespace = Namespc; |
| if (AddToKnown) |
| KnownNamespaces[Namespc] = false; |
| |
| if (II) { |
| PushOnScopeChains(Namespc, DeclRegionScope); |
| } else { |
| // Link the anonymous namespace into its parent. |
| DeclContext *Parent = CurContext->getRedeclContext(); |
| if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) { |
| TU->setAnonymousNamespace(Namespc); |
| } else { |
| cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc); |
| } |
| |
| CurContext->addDecl(Namespc); |
| |
| // C++ [namespace.unnamed]p1. An unnamed-namespace-definition |
| // behaves as if it were replaced by |
| // namespace unique { /* empty body */ } |
| // using namespace unique; |
| // namespace unique { namespace-body } |
| // where all occurrences of 'unique' in a translation unit are |
| // replaced by the same identifier and this identifier differs |
| // from all other identifiers in the entire program. |
| |
| // We just create the namespace with an empty name and then add an |
| // implicit using declaration, just like the standard suggests. |
| // |
| // CodeGen enforces the "universally unique" aspect by giving all |
| // declarations semantically contained within an anonymous |
| // namespace internal linkage. |
| |
| if (!PrevNS) { |
| UD = UsingDirectiveDecl::Create(Context, Parent, |
| /* 'using' */ LBrace, |
| /* 'namespace' */ SourceLocation(), |
| /* qualifier */ NestedNameSpecifierLoc(), |
| /* identifier */ SourceLocation(), |
| Namespc, |
| /* Ancestor */ Parent); |
| UD->setImplicit(); |
| Parent->addDecl(UD); |
| } |
| } |
| |
| ActOnDocumentableDecl(Namespc); |
| |
| // Although we could have an invalid decl (i.e. the namespace name is a |
| // redefinition), push it as current DeclContext and try to continue parsing. |
| // FIXME: We should be able to push Namespc here, so that the each DeclContext |
| // for the namespace has the declarations that showed up in that particular |
| // namespace definition. |
| PushDeclContext(NamespcScope, Namespc); |
| return Namespc; |
| } |
| |
| /// getNamespaceDecl - Returns the namespace a decl represents. If the decl |
| /// is a namespace alias, returns the namespace it points to. |
| static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) { |
| if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D)) |
| return AD->getNamespace(); |
| return dyn_cast_or_null<NamespaceDecl>(D); |
| } |
| |
| /// ActOnFinishNamespaceDef - This callback is called after a namespace is |
| /// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef. |
| void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) { |
| NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl); |
| assert(Namespc && "Invalid parameter, expected NamespaceDecl"); |
| Namespc->setRBraceLoc(RBrace); |
| PopDeclContext(); |
| if (Namespc->hasAttr<VisibilityAttr>()) |
| PopPragmaVisibility(true, RBrace); |
| } |
| |
| CXXRecordDecl *Sema::getStdBadAlloc() const { |
| return cast_or_null<CXXRecordDecl>( |
| StdBadAlloc.get(Context.getExternalSource())); |
| } |
| |
| EnumDecl *Sema::getStdAlignValT() const { |
| return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource())); |
| } |
| |
| NamespaceDecl *Sema::getStdNamespace() const { |
| return cast_or_null<NamespaceDecl>( |
| StdNamespace.get(Context.getExternalSource())); |
| } |
| |
| NamespaceDecl *Sema::lookupStdExperimentalNamespace() { |
| if (!StdExperimentalNamespaceCache) { |
| if (auto Std = getStdNamespace()) { |
| LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"), |
| SourceLocation(), LookupNamespaceName); |
| if (!LookupQualifiedName(Result, Std) || |
| !(StdExperimentalNamespaceCache = |
| Result.getAsSingle<NamespaceDecl>())) |
| Result.suppressDiagnostics(); |
| } |
| } |
| return StdExperimentalNamespaceCache; |
| } |
| |
| namespace { |
| |
| enum UnsupportedSTLSelect { |
| USS_InvalidMember, |
| USS_MissingMember, |
| USS_NonTrivial, |
| USS_Other |
| }; |
| |
| struct InvalidSTLDiagnoser { |
| Sema &S; |
| SourceLocation Loc; |
| QualType TyForDiags; |
| |
| QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "", |
| const VarDecl *VD = nullptr) { |
| { |
| auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported) |
| << TyForDiags << ((int)Sel); |
| if (Sel == USS_InvalidMember || Sel == USS_MissingMember) { |
| assert(!Name.empty()); |
| D << Name; |
| } |
| } |
| if (Sel == USS_InvalidMember) { |
| S.Diag(VD->getLocation(), diag::note_var_declared_here) |
| << VD << VD->getSourceRange(); |
| } |
| return QualType(); |
| } |
| }; |
| } // namespace |
| |
| QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind, |
| SourceLocation Loc) { |
| assert(getLangOpts().CPlusPlus && |
| "Looking for comparison category type outside of C++."); |
| |
| // Check if we've already successfully checked the comparison category type |
| // before. If so, skip checking it again. |
| ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind); |
| if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)]) |
| return Info->getType(); |
| |
| // If lookup failed |
| if (!Info) { |
| std::string NameForDiags = "std::"; |
| NameForDiags += ComparisonCategories::getCategoryString(Kind); |
| Diag(Loc, diag::err_implied_comparison_category_type_not_found) |
| << NameForDiags; |
| return QualType(); |
| } |
| |
| assert(Info->Kind == Kind); |
| assert(Info->Record); |
| |
| // Update the Record decl in case we encountered a forward declaration on our |
| // first pass. FIXME: This is a bit of a hack. |
| if (Info->Record->hasDefinition()) |
| Info->Record = Info->Record->getDefinition(); |
| |
| // Use an elaborated type for diagnostics which has a name containing the |
| // prepended 'std' namespace but not any inline namespace names. |
| QualType TyForDiags = [&]() { |
| auto *NNS = |
| NestedNameSpecifier::Create(Context, nullptr, getStdNamespace()); |
| return Context.getElaboratedType(ETK_None, NNS, Info->getType()); |
| }(); |
| |
| if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type)) |
| return QualType(); |
| |
| InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags}; |
| |
| if (!Info->Record->isTriviallyCopyable()) |
| return UnsupportedSTLError(USS_NonTrivial); |
| |
| for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) { |
| CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl(); |
| // Tolerate empty base classes. |
| if (Base->isEmpty()) |
| continue; |
| // Reject STL implementations which have at least one non-empty base. |
| return UnsupportedSTLError(); |
| } |
| |
| // Check that the STL has implemented the types using a single integer field. |
| // This expectation allows better codegen for builtin operators. We require: |
| // (1) The class has exactly one field. |
| // (2) The field is an integral or enumeration type. |
| auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end(); |
| if (std::distance(FIt, FEnd) != 1 || |
| !FIt->getType()->isIntegralOrEnumerationType()) { |
| return UnsupportedSTLError(); |
| } |
| |
| // Build each of the require values and store them in Info. |
| for (ComparisonCategoryResult CCR : |
| ComparisonCategories::getPossibleResultsForType(Kind)) { |
| StringRef MemName = ComparisonCategories::getResultString(CCR); |
| ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR); |
| |
| if (!ValInfo) |
| return UnsupportedSTLError(USS_MissingMember, MemName); |
| |
| VarDecl *VD = ValInfo->VD; |
| assert(VD && "should not be null!"); |
| |
| // Attempt to diagnose reasons why the STL definition of this type |
| // might be foobar, including it failing to be a constant expression. |
| // TODO Handle more ways the lookup or result can be invalid. |
| if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() || |
| !VD->checkInitIsICE()) |
| return UnsupportedSTLError(USS_InvalidMember, MemName, VD); |
| |
| // Attempt to evaluate the var decl as a constant expression and extract |
| // the value of its first field as a ICE. If this fails, the STL |
| // implementation is not supported. |
| if (!ValInfo->hasValidIntValue()) |
| return UnsupportedSTLError(); |
| |
| MarkVariableReferenced(Loc, VD); |
| } |
| |
| // We've successfully built the required types and expressions. Update |
| // the cache and return the newly cached value. |
| FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true; |
| return Info->getType(); |
| } |
| |
| /// Retrieve the special "std" namespace, which may require us to |
| /// implicitly define the namespace. |
| NamespaceDecl *Sema::getOrCreateStdNamespace() { |
| if (!StdNamespace) { |
| // The "std" namespace has not yet been defined, so build one implicitly. |
| StdNamespace = NamespaceDecl::Create(Context, |
| Context.getTranslationUnitDecl(), |
| /*Inline=*/false, |
| SourceLocation(), SourceLocation(), |
| &PP.getIdentifierTable().get("std"), |
| /*PrevDecl=*/nullptr); |
| getStdNamespace()->setImplicit(true); |
| } |
| |
| return getStdNamespace(); |
| } |
| |
| bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { |
| assert(getLangOpts().CPlusPlus && |
| "Looking for std::initializer_list outside of C++."); |
| |
| // We're looking for implicit instantiations of |
| // template <typename E> class std::initializer_list. |
| |
| if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it. |
| return false; |
| |
| ClassTemplateDecl *Template = nullptr; |
| const TemplateArgument *Arguments = nullptr; |
| |
| if (const RecordType *RT = Ty->getAs<RecordType>()) { |
| |
| ClassTemplateSpecializationDecl *Specialization = |
| dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); |
| if (!Specialization) |
| return false; |
| |
| Template = Specialization->getSpecializedTemplate(); |
| Arguments = Specialization->getTemplateArgs().data(); |
| } else if (const TemplateSpecializationType *TST = |
| Ty->getAs<TemplateSpecializationType>()) { |
| Template = dyn_cast_or_null<ClassTemplateDecl>( |
| TST->getTemplateName().getAsTemplateDecl()); |
| Arguments = TST->getArgs(); |
| } |
| if (!Template) |
| return false; |
| |
| if (!StdInitializerList) { |
| // Haven't recognized std::initializer_list yet, maybe this is it. |
| CXXRecordDecl *TemplateClass = Template->getTemplatedDecl(); |
| if (TemplateClass->getIdentifier() != |
| &PP.getIdentifierTable().get("initializer_list") || |
| !getStdNamespace()->InEnclosingNamespaceSetOf( |
| TemplateClass->getDeclContext())) |
| return false; |
| // This is a template called std::initializer_list, but is it the right |
| // template? |
| TemplateParameterList *Params = Template->getTemplateParameters(); |
| if (Params->getMinRequiredArguments() != 1) |
| return false; |
| if (!isa<TemplateTypeParmDecl>(Params->getParam(0))) |
| return false; |
| |
| // It's the right template. |
| StdInitializerList = Template; |
| } |
| |
| if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl()) |
| return false; |
| |
| // This is an instance of std::initializer_list. Find the argument type. |
| if (Element) |
| *Element = Arguments[0].getAsType(); |
| return true; |
| } |
| |
| static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){ |
| NamespaceDecl *Std = S.getStdNamespace(); |
| if (!Std) { |
| S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); |
| return nullptr; |
| } |
| |
| LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"), |
| Loc, Sema::LookupOrdinaryName); |
| if (!S.LookupQualifiedName(Result, Std)) { |
| S.Diag(Loc, diag::err_implied_std_initializer_list_not_found); |
| return nullptr; |
| } |
| ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>(); |
| if (!Template) { |
| Result.suppressDiagnostics(); |
| // We found something weird. Complain about the first thing we found. |
| NamedDecl *Found = *Result.begin(); |
| S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list); |
| return nullptr; |
| } |
| |
| // We found some template called std::initializer_list. Now verify that it's |
| // correct. |
| TemplateParameterList *Params = Template->getTemplateParameters(); |
| if (Params->getMinRequiredArguments() != 1 || |
| !isa<TemplateTypeParmDecl>(Params->getParam(0))) { |
| S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list); |
| return nullptr; |
| } |
| |
| return Template; |
| } |
| |
| QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { |
| if (!StdInitializerList) { |
| StdInitializerList = LookupStdInitializerList(*this, Loc); |
| if (!StdInitializerList) |
| return QualType(); |
| } |
| |
| TemplateArgumentListInfo Args(Loc, Loc); |
| Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element), |
| Context.getTrivialTypeSourceInfo(Element, |
| Loc))); |
| return Context.getCanonicalType( |
| CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); |
| } |
| |
| bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { |
| // C++ [dcl.init.list]p2: |
| // A constructor is an initializer-list constructor if its first parameter |
| // is of type std::initializer_list<E> or reference to possibly cv-qualified |
| // std::initializer_list<E> for some type E, and either there are no other |
| // parameters or else all other parameters have default arguments. |
| if (Ctor->getNumParams() < 1 || |
| (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg())) |
| return false; |
| |
| QualType ArgType = Ctor->getParamDecl(0)->getType(); |
| if (const ReferenceType *RT = ArgType->getAs<ReferenceType>()) |
| ArgType = RT->getPointeeType().getUnqualifiedType(); |
| |
| return isStdInitializerList(ArgType, nullptr); |
| } |
| |
| /// Determine whether a using statement is in a context where it will be |
| /// apply in all contexts. |
| static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { |
| switch (CurContext->getDeclKind()) { |
| case Decl::TranslationUnit: |
| return true; |
| case Decl::LinkageSpec: |
| return IsUsingDirectiveInToplevelContext(CurContext->getParent()); |
| default: |
| return false; |
| } |
| } |
| |
| namespace { |
| |
| // Callback to only accept typo corrections that are namespaces. |
| class NamespaceValidatorCCC : public CorrectionCandidateCallback { |
| public: |
| bool ValidateCandidate(const TypoCorrection &candidate) override { |
| if (NamedDecl *ND = candidate.getCorrectionDecl()) |
| return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); |
| return false; |
| } |
| }; |
| |
| } |
| |
| static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, |
| CXXScopeSpec &SS, |
| SourceLocation IdentLoc, |
| IdentifierInfo *Ident) { |
| R.clear(); |
| if (TypoCorrection Corrected = |
| S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, |
| llvm::make_unique<NamespaceValidatorCCC>(), |
| Sema::CTK_ErrorRecovery)) { |
| if (DeclContext *DC = S.computeDeclContext(SS, false)) { |
| std::string CorrectedStr(Corrected.getAsString(S.getLangOpts())); |
| bool DroppedSpecifier = Corrected.WillReplaceSpecifier() && |
| Ident->getName().equals(CorrectedStr); |
| S.diagnoseTypo(Corrected, |
| S.PDiag(diag::err_using_directive_member_suggest) |
| << Ident << DC << DroppedSpecifier << SS.getRange(), |
| S.PDiag(diag::note_namespace_defined_here)); |
| } else { |
| S.diagnoseTypo(Corrected, |
| S.PDiag(diag::err_using_directive_suggest) << Ident, |
| S.PDiag(diag::note_namespace_defined_here)); |
| } |
| R.addDecl(Corrected.getFoundDecl()); |
| return true; |
| } |
| return false; |
| } |
| |
| Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, |
| SourceLocation NamespcLoc, CXXScopeSpec &SS, |
| SourceLocation IdentLoc, |
| IdentifierInfo *NamespcName, |
| const ParsedAttributesView &AttrList) { |
| assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); |
| assert(NamespcName && "Invalid NamespcName."); |
| assert(IdentLoc.isValid() && "Invalid NamespceName location."); |
| |
| // This can only happen along a recovery path. |
| while (S->isTemplateParamScope()) |
| S = S->getParent(); |
| assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); |
| |
| UsingDirectiveDecl *UDir = nullptr; |
| NestedNameSpecifier *Qualifier = nullptr; |
| if (SS.isSet()) |
| Qualifier = SS.getScopeRep(); |
| |
| // Lookup namespace name. |
| LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName); |
| LookupParsedName(R, S, &SS); |
| if (R.isAmbiguous()) |
| return nullptr; |
| |
| if (R.empty()) { |
| R.clear(); |
| // Allow "using namespace std;" or "using namespace ::std;" even if |
| // "std" hasn't been defined yet, for GCC compatibility. |
| if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && |
| NamespcName->isStr("std")) { |
| Diag(IdentLoc, diag::ext_using_undefined_std); |
| R.addDecl(getOrCreateStdNamespace()); |
| R.resolveKind(); |
| } |
| // Otherwise, attempt typo correction. |
| else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); |
| } |
| |
| if (!R.empty()) { |
| NamedDecl *Named = R.getRepresentativeDecl(); |
| NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>(); |
| assert(NS && "expected namespace decl"); |
| |
| // The use of a nested name specifier may trigger deprecation warnings. |
| DiagnoseUseOfDecl(Named, IdentLoc); |
| |
| // C++ [namespace.udir]p1: |
| // A using-directive specifies that the names in the nominated |
| // namespace can be used in the scope in which the |
| // using-directive appears after the using-directive. During |
| // unqualified name lookup (3.4.1), the names appear as if they |
| // were declared in the nearest enclosing namespace which |
| // contains both the using-directive and the nominated |
| // namespace. [Note: in this context, "contains" means "contains |
| // directly or indirectly". ] |
| |
| // Find enclosing context containing both using-directive and |
| // nominated namespace. |
| DeclContext *CommonAncestor = NS; |
| while (CommonAncestor && !CommonAncestor->Encloses(CurContext)) |
| CommonAncestor = CommonAncestor->getParent(); |
| |
| UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc, |
| SS.getWithLocInContext(Context), |
| IdentLoc, Named, CommonAncestor); |
| |
| if (IsUsingDirectiveInToplevelContext(CurContext) && |
| !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { |
| Diag(IdentLoc, diag::warn_using_directive_in_header); |
| } |
| |
| PushUsingDirective(S, UDir); |
| } else { |
| Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); |
| } |
| |
| if (UDir) |
| ProcessDeclAttributeList(S, UDir, AttrList); |
| |
| return UDir; |
| } |
| |
| void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { |
| // If the scope has an associated entity and the using directive is at |
| // namespace or translation unit scope, add the UsingDirectiveDecl into |
| // its lookup structure so qualified name lookup can find it. |
| DeclContext *Ctx = S->getEntity(); |
| if (Ctx && !Ctx->isFunctionOrMethod()) |
| Ctx->addDecl(UDir); |
| else |
| // Otherwise, it is at block scope. The using-directives will affect lookup |
| // only to the end of the scope. |
| S->PushUsingDirective(UDir); |
| } |
| |
| Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, |
| SourceLocation UsingLoc, |
| SourceLocation TypenameLoc, CXXScopeSpec &SS, |
| UnqualifiedId &Name, |
| SourceLocation EllipsisLoc, |
| const ParsedAttributesView &AttrList) { |
| assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); |
| |
| if (SS.isEmpty()) { |
| Diag(Name.getLocStart(), diag::err_using_requires_qualname); |
| return nullptr; |
| } |
| |
| switch (Name.getKind()) { |
| case UnqualifiedIdKind::IK_ImplicitSelfParam: |
| case UnqualifiedIdKind::IK_Identifier: |
| case UnqualifiedIdKind::IK_OperatorFunctionId: |
| case UnqualifiedIdKind::IK_LiteralOperatorId: |
| case UnqualifiedIdKind::IK_ConversionFunctionId: |
| break; |
| |
| case UnqualifiedIdKind::IK_ConstructorName: |
| case UnqualifiedIdKind::IK_ConstructorTemplateId: |
| // C++11 inheriting constructors. |
| Diag(Name.getLocStart(), |
| getLangOpts().CPlusPlus11 ? |
| diag::warn_cxx98_compat_using_decl_constructor : |
| diag::err_using_decl_constructor) |
| << SS.getRange(); |
| |
| if (getLangOpts().CPlusPlus11) break; |
| |
| return nullptr; |
| |
| case UnqualifiedIdKind::IK_DestructorName: |
| Diag(Name.getLocStart(), diag::err_using_decl_destructor) |
| << SS.getRange(); |
| return nullptr; |
| |
| case UnqualifiedIdKind::IK_TemplateId: |
| Diag(Name.getLocStart(), diag::err_using_decl_template_id) |
| << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc); |
| return nullptr; |
| |
| case UnqualifiedIdKind::IK_DeductionGuideName: |
| llvm_unreachable("cannot parse qualified deduction guide name"); |
| } |
| |
| DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); |
| DeclarationName TargetName = TargetNameInfo.getName(); |
| if (!TargetName) |
| return nullptr; |
| |
| // Warn about access declarations. |
| if (UsingLoc.isInvalid()) { |
| Diag(Name.getLocStart(), |
| getLangOpts().CPlusPlus11 ? diag::err_access_decl |
| : diag::warn_access_decl_deprecated) |
| << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); |
| } |
| |
| if (EllipsisLoc.isInvalid()) { |
| if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || |
| DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) |
| return nullptr; |
| } else { |
| if (!SS.getScopeRep()->containsUnexpandedParameterPack() && |
| !TargetNameInfo.containsUnexpandedParameterPack()) { |
| Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) |
| << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); |
| EllipsisLoc = SourceLocation(); |
| } |
| } |
| |
| NamedDecl *UD = |
| BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc, |
| SS, TargetNameInfo, EllipsisLoc, AttrList, |
| /*IsInstantiation*/false); |
| if (UD) |
| PushOnScopeChains(UD, S, /*AddToContext*/ false); |
| |
| return UD; |
| } |
| |
| /// Determine whether a using declaration considers the given |
| /// declarations as "equivalent", e.g., if they are redeclarations of |
| /// the same entity or are both typedefs of the same type. |
| static bool |
| IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) { |
| if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) |
| return true; |
| |
| if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1)) |
| if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) |
| return Context.hasSameType(TD1->getUnderlyingType(), |
| TD2->getUnderlyingType()); |
| |
| return false; |
| } |
| |
| |
| /// Determines whether to create a using shadow decl for a particular |
| /// decl, given the set of decls existing prior to this using lookup. |
| bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, |
| const LookupResult &Previous, |
| UsingShadowDecl *&PrevShadow) { |
| // Diagnose finding a decl which is not from a base class of the |
| // current class. We do this now because there are cases where this |
| // function will silently decide not to build a shadow decl, which |
| // will pre-empt further diagnostics. |
| // |
| // We don't need to do this in C++11 because we do the check once on |
| // the qualifier. |
| // |
| // FIXME: diagnose the following if we care enough: |
| // struct A { int foo; }; |
| // struct B : A { using A::foo; }; |
| // template <class T> struct C : A {}; |
| // template <class T> struct D : C<T> { using B::foo; } // <--- |
| // This is invalid (during instantiation) in C++03 because B::foo |
| // resolves to the using decl in B, which is not a base class of D<T>. |
| // We can't diagnose it immediately because C<T> is an unknown |
| // specialization. The UsingShadowDecl in D<T> then points directly |
| // to A::foo, which will look well-formed when we instantiate. |
| // The right solution is to not collapse the shadow-decl chain. |
| if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) { |
| DeclContext *OrigDC = Orig->getDeclContext(); |
| |
| // Handle enums and anonymous structs. |
| if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent(); |
| CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC); |
| while (OrigRec->isAnonymousStructOrUnion()) |
| OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext()); |
| |
| if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) { |
| if (OrigDC == CurContext) { |
| Diag(Using->getLocation(), |
| diag::err_using_decl_nested_name_specifier_is_current_class) |
| << Using->getQualifierLoc().getSourceRange(); |
| Diag(Orig->getLocation(), diag::note_using_decl_target); |
| Using->setInvalidDecl(); |
| return true; |
| } |
| |
| Diag(Using->getQualifierLoc().getBeginLoc(), |
| diag::err_using_decl_nested_name_specifier_is_not_base_class) |
| << Using->getQualifier() |
| << cast<CXXRecordDecl>(CurContext) |
| << Using->getQualifierLoc().getSourceRange(); |
| Diag(Orig->getLocation(), diag::note_using_decl_target); |
| Using->setInvalidDecl(); |
| return true; |
| } |
| } |
| |
| if (Previous.empty()) return false; |
| |
| NamedDecl *Target = Orig; |
| if (isa<UsingShadowDecl>(Target)) |
| Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); |
| |
| // If the target happens to be one of the previous declarations, we |
| // don't have a conflict. |
| // |
| // FIXME: but we might be increasing its access, in which case we |
| // should redeclare it. |
| NamedDecl *NonTag = nullptr, *Tag = nullptr; |
| bool FoundEquivalentDecl = false; |
| for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); |
| I != E; ++I) { |
| NamedDecl *D = (*I)->getUnderlyingDecl(); |
| // We can have UsingDecls in our Previous results because we use the same |
| // LookupResult for checking whether the UsingDecl itself is a valid |
| // redeclaration. |
| if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D)) |
| continue; |
| |
| if (auto *RD = dyn_cast<CXXRecordDecl>(D)) { |
| // C++ [class.mem]p19: |
| // If T is the name of a class, then [every named member other than |
| // a non-static data member] shall have a name different from T |
| if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) && |
| !isa<IndirectFieldDecl>(Target) && |
| !isa<UnresolvedUsingValueDecl>(Target) && |
| DiagnoseClassNameShadow( |
| CurContext, |
| DeclarationNameInfo(Using->getDeclName(), Using->getLocation()))) |
| return true; |
| } |
| |
| if (IsEquivalentForUsingDecl(Context, D, Target)) { |
| if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I)) |
| PrevShadow = Shadow; |
| FoundEquivalentDecl = true; |
| } else if (isEquivalentInternalLinkageDeclaration(D, Target)) { |
| // We don't conflict with an existing using shadow decl of an equivalent |
| // declaration, but we're not a redeclaration of it. |
| FoundEquivalentDecl = true; |
| } |
| |
| if (isVisible(D)) |
| (isa<TagDecl>(D) ? Tag : NonTag) = D; |
| } |
| |
| if (FoundEquivalentDecl) |
| return false; |
| |
| if (FunctionDecl *FD = Target->getAsFunction()) { |
| NamedDecl *OldDecl = nullptr; |
| switch (CheckOverload(nullptr, FD, Previous, OldDecl, |
| /*IsForUsingDecl*/ true)) { |
| case Ovl_Overload: |
| return false; |
| |
| case Ovl_NonFunction: |
| Diag(Using->getLocation(), diag::err_using_decl_conflict); |
| break; |
| |
| // We found a decl with the exact signature. |
| case Ovl_Match: |
| // If we're in a record, we want to hide the target, so we |
| // return true (without a diagnostic) to tell the caller not to |
| // build a shadow decl. |
| if (CurContext->isRecord()) |
| return true; |
| |
| // If we're not in a record, this is an error. |
| Diag(Using->getLocation(), diag::err_using_decl_conflict); |
| break; |
| } |
| |
| Diag(Target->getLocation(), diag::note_using_decl_target); |
| Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); |
| Using->setInvalidDecl(); |
| return true; |
| } |
| |
| // Target is not a function. |
| |
| if (isa<TagDecl>(Target)) { |
| // No conflict between a tag and a non-tag. |
| if (!Tag) return false; |
| |
| Diag(Using->getLocation(), diag::err_using_decl_conflict); |
| Diag(Target->getLocation(), diag::note_using_decl_target); |
| Diag(Tag->getLocation(), diag::note_using_decl_conflict); |
| Using->setInvalidDecl(); |
| return true; |
| } |
| |
| // No conflict between a tag and a non-tag. |
| if (!NonTag) return false; |
| |
| Diag(Using->getLocation(), diag::err_using_decl_conflict); |
| Diag(Target->getLocation(), diag::note_using_decl_target); |
| Diag(NonTag->getLocation(), diag::note_using_decl_conflict); |
| Using->setInvalidDecl(); |
| return true; |
| } |
| |
| /// Determine whether a direct base class is a virtual base class. |
| static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) { |
| if (!Derived->getNumVBases()) |
| return false; |
| for (auto &B : Derived->bases()) |
| if (B.getType()->getAsCXXRecordDecl() == Base) |
| return B.isVirtual(); |
| llvm_unreachable("not a direct base class"); |
| } |
| |
| /// Builds a shadow declaration corresponding to a 'using' declaration. |
| UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, |
| UsingDecl *UD, |
| NamedDecl *Orig, |
| UsingShadowDecl *PrevDecl) { |
| // If we resolved to another shadow declaration, just coalesce them. |
| NamedDecl *Target = Orig; |
| if (isa<UsingShadowDecl>(Target)) { |
| Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); |
| assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration"); |
| } |
| |
| NamedDecl *NonTemplateTarget = Target; |
| if (auto *TargetTD = dyn_cast<TemplateDecl>(Target)) |
| NonTemplateTarget = TargetTD->getTemplatedDecl(); |
| |
| UsingShadowDecl *Shadow; |
| if (isa<CXXConstructorDecl>(NonTemplateTarget)) { |
| bool IsVirtualBase = |
| isVirtualDirectBase(cast<CXXRecordDecl>(CurContext), |
| UD->getQualifier()->getAsRecordDecl()); |
| Shadow = ConstructorUsingShadowDecl::Create( |
| Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase); |
| } else { |
| Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD, |
| Target); |
| } |
| UD->addShadowDecl(Shadow); |
| |
| Shadow->setAccess(UD->getAccess()); |
| if (Orig->isInvalidDecl() || UD->isInvalidDecl()) |
| Shadow->setInvalidDecl(); |
| |
| Shadow->setPreviousDecl(PrevDecl); |
| |
| if (S) |
| PushOnScopeChains(Shadow, S); |
| else |
| CurContext->addDecl(Shadow); |
| |
| |
| return Shadow; |
| } |
| |
| /// Hides a using shadow declaration. This is required by the current |
| /// using-decl implementation when a resolvable using declaration in a |
| /// class is followed by a declaration which would hide or override |
| /// one or more of the using decl's targets; for example: |
| /// |
| /// struct Base { void foo(int); }; |
| /// struct Derived : Base { |
| /// using Base::foo; |
| /// void foo(int); |
| /// }; |
| /// |
| /// The governing language is C++03 [namespace.udecl]p12: |
| /// |
| /// When a using-declaration brings names from a base class into a |
| /// derived class scope, member functions in the derived class |
| /// override and/or hide member functions with the same name and |
| /// parameter types in a base class (rather than conflicting). |
| /// |
| /// There are two ways to implement this: |
| /// (1) optimistically create shadow decls when they're not hidden |
| /// by existing declarations, or |
| /// (2) don't create any shadow decls (or at least don't make them |
| /// visible) until we've fully parsed/instantiated the class. |
| /// The problem with (1) is that we might have to retroactively remove |
| /// a shadow decl, which requires several O(n) operations because the |
| /// decl structures are (very reasonably) not designed for removal. |
| /// (2) avoids this but is very fiddly and phase-dependent. |
| void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { |
| if (Shadow->getDeclName().getNameKind() == |
| DeclarationName::CXXConversionFunctionName) |
| cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow); |
| |
| // Remove it from the DeclContext... |
| Shadow->getDeclContext()->removeDecl(Shadow); |
| |
| // ...and the scope, if applicable... |
| if (S) { |
| S->RemoveDecl(Shadow); |
| IdResolver.RemoveDecl(Shadow); |
| } |
| |
| // ...and the using decl. |
| Shadow->getUsingDecl()->removeShadowDecl(Shadow); |
| |
| // TODO: complain somehow if Shadow was used. It shouldn't |
| // be possible for this to happen, because...? |
| } |
| |
| /// Find the base specifier for a base class with the given type. |
| static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived, |
| QualType DesiredBase, |
| bool &AnyDependentBases) { |
| // Check whether the named type is a direct base class. |
| CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified(); |
| for (auto &Base : Derived->bases()) { |
| CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified(); |
| if (CanonicalDesiredBase == BaseType) |
| return &Base; |
| if (BaseType->isDependentType()) |
| AnyDependentBases = true; |
| } |
| return nullptr; |
| } |
| |
| namespace { |
| class UsingValidatorCCC : public CorrectionCandidateCallback { |
| public: |
| UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation, |
| NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf) |
| : HasTypenameKeyword(HasTypenameKeyword), |
| IsInstantiation(IsInstantiation), OldNNS(NNS), |
| RequireMemberOf(RequireMemberOf) {} |
| |
| bool ValidateCandidate(const TypoCorrection &Candidate) override { |
| NamedDecl *ND = Candidate.getCorrectionDecl(); |
| |
| // Keywords are not valid here. |
| if (!ND || isa<NamespaceDecl>(ND)) |
| return false; |
| |
| // Completely unqualified names are invalid for a 'using' declaration. |
| if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier()) |
| return false; |
| |
| // FIXME: Don't correct to a name that CheckUsingDeclRedeclaration would |
| // reject. |
| |
| if (RequireMemberOf) { |
| auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND); |
| if (FoundRecord && FoundRecord->isInjectedClassName()) { |
| // No-one ever wants a using-declaration to name an injected-class-name |
| // of a base class, unless they're declaring an inheriting constructor. |
| ASTContext &Ctx = ND->getASTContext(); |
| if (!Ctx.getLangOpts().CPlusPlus11) |
| return false; |
| QualType FoundType = Ctx.getRecordType(FoundRecord); |
| |
| // Check that the injected-class-name is named as a member of its own |
| // type; we don't want to suggest 'using Derived::Base;', since that |
| // means something else. |
| NestedNameSpecifier *Specifier = |
| Candidate.WillReplaceSpecifier() |
| ? Candidate.getCorrectionSpecifier() |
| : OldNNS; |
| if (!Specifier->getAsType() || |
| !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType)) |
| return false; |
| |
| // Check that this inheriting constructor declaration actually names a |
| // direct base class of the current class. |
| bool AnyDependentBases = false; |
| if (!findDirectBaseWithType(RequireMemberOf, |
| Ctx.getRecordType(FoundRecord), |
| AnyDependentBases) && |
| !AnyDependentBases) |
| return false; |
| } else { |
| auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext()); |
| if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD)) |
| return false; |
| |
| // FIXME: Check that the base class member is accessible? |
| } |
| } else { |
| auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND); |
| if (FoundRecord && FoundRecord->isInjectedClassName()) |
| return false; |
| } |
| |
| if (isa<TypeDecl>(ND)) |
| return HasTypenameKeyword || !IsInstantiation; |
| |
| return !HasTypenameKeyword; |
| } |
| |
| private: |
| bool HasTypenameKeyword; |
| bool IsInstantiation; |
| NestedNameSpecifier *OldNNS; |
| CXXRecordDecl *RequireMemberOf; |
| }; |
| } // end anonymous namespace |
| |
| /// Builds a using declaration. |
| /// |
| /// \param IsInstantiation - Whether this call arises from an |
| /// instantiation of an unresolved using declaration. We treat |
| /// the lookup differently for these declarations. |
| NamedDecl *Sema::BuildUsingDeclaration( |
| Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, |
| bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, |
| DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, |
| const ParsedAttributesView &AttrList, bool IsInstantiation) { |
| assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); |
| SourceLocation IdentLoc = NameInfo.getLoc(); |
| assert(IdentLoc.isValid() && "Invalid TargetName location."); |
| |
| // FIXME: We ignore attributes for now. |
| |
| // For an inheriting constructor declaration, the name of the using |
| // declaration is the name of a constructor in this class, not in the |
| // base class. |
| DeclarationNameInfo UsingName = NameInfo; |
| if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName) |
| if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext)) |
| UsingName.setName(Context.DeclarationNames.getCXXConstructorName( |
| Context.getCanonicalType(Context.getRecordType(RD)))); |
| |
| // Do the redeclaration lookup in the current scope. |
| LookupResult Previous(*this, UsingName, LookupUsingDeclName, |
| ForVisibleRedeclaration); |
| Previous.setHideTags(false); |
| if (S) { |
| LookupName(Previous, S); |
| |
| // It is really dumb that we have to do this. |
| LookupResult::Filter F = Previous.makeFilter(); |
| while (F.hasNext()) { |
| NamedDecl *D = F.next(); |
| if (!isDeclInScope(D, CurContext, S)) |
| F.erase(); |
| // If we found a local extern declaration that's not ordinarily visible, |
| // and this declaration is being added to a non-block scope, ignore it. |
| // We're only checking for scope conflicts here, not also for violations |
| // of the linkage rules. |
| else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() && |
| !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary)) |
| F.erase(); |
| } |
| F.done(); |
| } else { |
| assert(IsInstantiation && "no scope in non-instantiation"); |
| if (CurContext->isRecord()) |
| LookupQualifiedName(Previous, CurContext); |
| else { |
| // No redeclaration check is needed here; in non-member contexts we |
| // diagnosed all possible conflicts with other using-declarations when |
| // building the template: |
| // |
| // For a dependent non-type using declaration, the only valid case is |
| // if we instantiate to a single enumerator. We check for conflicts |
| // between shadow declarations we introduce, and we check in the template |
| // definition for conflicts between a non-type using declaration and any |
| // other declaration, which together covers all cases. |
| // |
| // A dependent typename using declaration will never successfully |
| // instantiate, since it will always name a class member, so we reject |
| // that in the template definition. |
| } |
| } |
| |
| // Check for invalid redeclarations. |
| if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword, |
| SS, IdentLoc, Previous)) |
| return nullptr; |
| |
| // Check for bad qualifiers. |
| if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo, |
| IdentLoc)) |
| return nullptr; |
| |
| DeclContext *LookupContext = computeDeclContext(SS); |
| NamedDecl *D; |
| NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); |
| if (!LookupContext || EllipsisLoc.isValid()) { |
| if (HasTypenameKeyword) { |
| // FIXME: not all declaration name kinds are legal here |
| D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, |
| UsingLoc, TypenameLoc, |
| QualifierLoc, |
| IdentLoc, NameInfo.getName(), |
| EllipsisLoc); |
| } else { |
| D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, |
| QualifierLoc, NameInfo, EllipsisLoc); |
| } |
| D->setAccess(AS); |
| CurContext->addDecl(D); |
| return D; |
| } |
| |
| auto Build = [&](bool Invalid) { |
| UsingDecl *UD = |
| UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc, |
| UsingName, HasTypenameKeyword); |
| UD->setAccess(AS); |
| CurContext->addDecl(UD); |
| UD->setInvalidDecl(Invalid); |
| return UD; |
| }; |
| auto BuildInvalid = [&]{ return Build(true); }; |
| auto BuildValid = [&]{ return Build(false); }; |
| |
| if (RequireCompleteDeclContext(SS, LookupContext)) |
| return BuildInvalid(); |
| |
| // Look up the target name. |
| LookupResult R(*this, NameInfo, LookupOrdinaryName); |
| |
| // Unlike most lookups, we don't always want to hide tag |
| // declarations: tag names are visible through the using declaration |
| // even if hidden by ordinary names, *except* in a dependent context |
| // where it's important for the sanity of two-phase lookup. |
| if (!IsInstantiation) |
| R.setHideTags(false); |
| |
| // For the purposes of this lookup, we have a base object type |
| // equal to that of the current context. |
| if (CurContext->isRecord()) { |
| R.setBaseObjectType( |
| Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext))); |
| } |
| |
| LookupQualifiedName(R, LookupContext); |
| |
| // Try to correct typos if possible. If constructor name lookup finds no |
| // results, that means the named class has no explicit constructors, and we |
| // suppressed declaring implicit ones (probably because it's dependent or |
| // invalid). |
| if (R.empty() && |
| NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) { |
| // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes |
| // it will believe that glibc provides a ::gets in cases where it does not, |
| // and will try to pull it into namespace std with a using-declaration. |
| // Just ignore the using-declaration in that case. |
| auto *II = NameInfo.getName().getAsIdentifierInfo(); |
| if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") && |
| CurContext->isStdNamespace() && |
| isa<TranslationUnitDecl>(LookupContext) && |
| getSourceManager().isInSystemHeader(UsingLoc)) |
| return nullptr; |
| if (TypoCorrection Corrected = CorrectTypo( |
| R.getLookupNameInfo(), R.getLookupKind(), S, &SS, |
| llvm::make_unique<UsingValidatorCCC>( |
| HasTypenameKeyword, IsInstantiation, SS.getScopeRep(), |
| dyn_cast<CXXRecordDecl>(CurContext)), |
| CTK_ErrorRecovery)) { |
| // We reject candidates where DroppedSpecifier == true, hence the |
| // literal '0' below. |
| diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest) |
| << NameInfo.getName() << LookupContext << 0 |
| << SS.getRange()); |
| |
| // If we picked a correction with no attached Decl we can't do anything |
| // useful with it, bail out. |
| NamedDecl *ND = Corrected.getCorrectionDecl(); |
| if (!ND) |
| return BuildInvalid(); |
| |
| // If we corrected to an inheriting constructor, handle it as one. |
| auto *RD = dyn_cast<CXXRecordDecl>(ND); |
| if (RD && RD->isInjectedClassName()) { |
| // The parent of the injected class name is the class itself. |
| RD = cast<CXXRecordDecl>(RD->getParent()); |
| |
| // Fix up the information we'll use to build the using declaration. |
| if (Corrected.WillReplaceSpecifier()) { |
| NestedNameSpecifierLocBuilder Builder; |
| Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), |
| QualifierLoc.getSourceRange()); |
| QualifierLoc = Builder.getWithLocInContext(Context); |
| } |
| |
| // In this case, the name we introduce is the name of a derived class |
| // constructor. |
| auto *CurClass = cast<CXXRecordDecl>(CurContext); |
| UsingName.setName(Context.DeclarationNames.getCXXConstructorName( |
| Context.getCanonicalType(Context.getRecordType(CurClass)))); |
| UsingName.setNamedTypeInfo(nullptr); |
| for (auto *Ctor : LookupConstructors(RD)) |
| R.addDecl(Ctor); |
| R.resolveKind(); |
| } else { |
| // FIXME: Pick up all the declarations if we found an overloaded |
| // function. |
| UsingName.setName(ND->getDeclName()); |
| R.addDecl(ND); |
| } |
| } else { |
| Diag(IdentLoc, diag::err_no_member) |
| << NameInfo.getName() << LookupContext << SS.getRange(); |
| return BuildInvalid(); |
| } |
| } |
| |
| if (R.isAmbiguous()) |
| return BuildInvalid(); |
| |
| if (HasTypenameKeyword) { |
| // If we asked for a typename and got a non-type decl, error out. |
| if (!R.getAsSingle<TypeDecl>()) { |
| Diag(IdentLoc, diag::err_using_typename_non_type); |
| for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) |
| Diag((*I)->getUnderlyingDecl()->getLocation(), |
| diag::note_using_decl_target); |
| return BuildInvalid(); |
| } |
| } else { |
| // If we asked for a non-typename and we got a type, error out, |
| // but only if this is an instantiation of an unresolved using |
| // decl. Otherwise just silently find the type name. |
| if (IsInstantiation && R.getAsSingle<TypeDecl>()) { |
| Diag(IdentLoc, diag::err_using_dependent_value_is_type); |
| Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); |
| return BuildInvalid(); |
| } |
| } |
| |
| // C++14 [namespace.udecl]p6: |
| // A using-declaration shall not name a namespace. |
| if (R.getAsSingle<NamespaceDecl>()) { |
| Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) |
| << SS.getRange(); |
| return BuildInvalid(); |
| } |
| |
| // C++14 [namespace.udecl]p7: |
| // A using-declaration shall not name a scoped enumerator. |
| if (auto *ED = R.getAsSingle<EnumConstantDecl>()) { |
| if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) { |
| Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum) |
| << SS.getRange(); |
| return BuildInvalid(); |
| } |
| } |
| |
| UsingDecl *UD = BuildValid(); |
| |
| // Some additional rules apply to inheriting constructors. |
| if (UsingName.getName().getNameKind() == |
| DeclarationName::CXXConstructorName) { |
| // Suppress access diagnostics; the access check is instead performed at the |
| // point of use for an inheriting constructor. |
| R.suppressDiagnostics(); |
| if (CheckInheritingConstructorUsingDecl(UD)) |
| return UD; |
| } |
| |
| for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { |
| UsingShadowDecl *PrevDecl = nullptr; |
| if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) |
| BuildUsingShadowDecl(S, UD, *I, PrevDecl); |
| } |
| |
| return UD; |
| } |
| |
| NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, |
| ArrayRef<NamedDecl *> Expansions) { |
| assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) || |
| isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) || |
| isa<UsingPackDecl>(InstantiatedFrom)); |
| |
| auto *UPD = |
| UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions); |
| UPD->setAccess(InstantiatedFrom->getAccess()); |
| CurContext->addDecl(UPD); |
| return UPD; |
| } |
| |
| /// Additional checks for a using declaration referring to a constructor name. |
| bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { |
| assert(!UD->hasTypename() && "expecting a constructor name"); |
| |
| const Type *SourceType = UD->getQualifier()->getAsType(); |
| assert(SourceType && |
| "Using decl naming constructor doesn't have type in scope spec."); |
| CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext); |
| |
| // Check whether the named type is a direct base class. |
| bool AnyDependentBases = false; |
| auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0), |
| AnyDependentBases); |
| if (!Base && !AnyDependentBases) { |
| Diag(UD->getUsingLoc(), |
| diag::err_using_decl_constructor_not_in_direct_base) |
| << UD->getNameInfo().getSourceRange() |
| << QualType(SourceType, 0) << TargetClass; |
| UD->setInvalidDecl(); |
| return true; |
| } |
| |
| if (Base) |
| Base->setInheritConstructors(); |
| |
| return false; |
| } |
| |
| /// Checks that the given using declaration is not an invalid |
| /// redeclaration. Note that this is checking only for the using decl |
| /// itself, not for any ill-formedness among the UsingShadowDecls. |
| bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, |
| bool HasTypenameKeyword, |
| const CXXScopeSpec &SS, |
| SourceLocation NameLoc, |
| const LookupResult &Prev) { |
| NestedNameSpecifier *Qual = SS.getScopeRep(); |
| |
| // C++03 [namespace.udecl]p8: |
| // C++0x [namespace.udecl]p10: |
| // A using-declaration is a declaration and can therefore be used |
| // repeatedly where (and only where) multiple declarations are |
| // allowed. |
| // |
| // That's in non-member contexts. |
| if (!CurContext->getRedeclContext()->isRecord()) { |
| // A dependent qualifier outside a class can only ever resolve to an |
| // enumeration type. Therefore it conflicts with any other non-type |
| // declaration in the same scope. |
| // FIXME: How should we check for dependent type-type conflicts at block |
| // scope? |
| if (Qual->isDependent() && !HasTypenameKeyword) { |
| for (auto *D : Prev) { |
| if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) { |
| bool OldCouldBeEnumerator = |
| isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D); |
| Diag(NameLoc, |
| OldCouldBeEnumerator ? diag::err_redefinition |
| : diag::err_redefinition_different_kind) |
| << Prev.getLookupName(); |
| Diag(D->getLocation(), diag::note_previous_definition); |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) { |
| NamedDecl *D = *I; |
| |
| bool DTypename; |
| NestedNameSpecifier *DQual; |
| if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { |
| DTypename = UD->hasTypename(); |
| DQual = UD->getQualifier(); |
| } else if (UnresolvedUsingValueDecl *UD |
| = dyn_cast<UnresolvedUsingValueDecl>(D)) { |
| DTypename = false; |
| DQual = UD->getQualifier(); |
| } else if (UnresolvedUsingTypenameDecl *UD |
| = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { |
| DTypename = true; |
| DQual = UD->getQualifier(); |
| } else continue; |
| |
| // using decls differ if one says 'typename' and the other doesn't. |
| // FIXME: non-dependent using decls? |
| if (HasTypenameKeyword != DTypename) continue; |
| |
| // using decls differ if they name different scopes (but note that |
| // template instantiation can cause this check to trigger when it |
| // didn't before instantiation). |
| if (Context.getCanonicalNestedNameSpecifier(Qual) != |
| Context.getCanonicalNestedNameSpecifier(DQual)) |
| continue; |
| |
| Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange(); |
| Diag(D->getLocation(), diag::note_using_decl) << 1; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| |
| /// Checks that the given nested-name qualifier used in a using decl |
| /// in the current context is appropriately related to the current |
| /// scope. If an error is found, diagnoses it and returns true. |
| bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, |
| bool HasTypename, |
| const CXXScopeSpec &SS, |
| const DeclarationNameInfo &NameInfo, |
| SourceLocation NameLoc) { |
| DeclContext *NamedContext = computeDeclContext(SS); |
| |
| if (!CurContext->isRecord()) { |
| // C++03 [namespace.udecl]p3: |
| // C++0x [namespace.udecl]p8: |
| // A using-declaration for a class member shall be a member-declaration. |
| |
| // If we weren't able to compute a valid scope, it might validly be a |
| // dependent class scope or a dependent enumeration unscoped scope. If |
| // we have a 'typename' keyword, the scope must resolve to a class type. |
| if ((HasTypename && !NamedContext) || |
| (NamedContext && NamedContext->getRedeclContext()->isRecord())) { |
| auto *RD = NamedContext |
| ? cast<CXXRecordDecl>(NamedContext->getRedeclContext()) |
| : nullptr; |
| if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD)) |
| RD = nullptr; |
| |
| Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member) |
| << SS.getRange(); |
| |
| // If we have a complete, non-dependent source type, try to suggest a |
| // way to get the same effect. |
| if (!RD) |
| return true; |
| |
| // Find what this using-declaration was referring to. |
| LookupResult R(*this, NameInfo, LookupOrdinaryName); |
| R.setHideTags(false); |
| R.suppressDiagnostics(); |
| LookupQualifiedName(R, RD); |
| |
| if (R.getAsSingle<TypeDecl>()) { |
| if (getLangOpts().CPlusPlus11) { |
| // Convert 'using X::Y;' to 'using Y = X::Y;'. |
| Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround) |
| << 0 // alias declaration |
| << FixItHint::CreateInsertion(SS.getBeginLoc(), |
| NameInfo.getName().getAsString() + |
| " = "); |
| } else { |
| // Convert 'using X::Y;' to 'typedef X::Y Y;'. |
| SourceLocation InsertLoc = |
| getLocForEndOfToken(NameInfo.getLocEnd()); |
| Diag(InsertLoc, diag::note_using_decl_class_member_workaround) |
| << 1 // typedef declaration |
| << FixItHint::CreateReplacement(UsingLoc, "typedef") |
| << FixItHint::CreateInsertion( |
| InsertLoc, " " + NameInfo.getName().getAsString()); |
| } |
| } else if (R.getAsSingle<VarDecl>()) { |
| // Don't provide a fixit outside C++11 mode; we don't want to suggest |
| // repeating the type of the static data member here. |
| FixItHint FixIt; |
| if (getLangOpts().CPlusPlus11) { |
| // Convert 'using X::Y;' to 'auto &Y = X::Y;'. |
| FixIt = FixItHint::CreateReplacement( |
| UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = "); |
| } |
| |
| Diag(UsingLoc, diag::note_using_decl_class_member_workaround) |
| << 2 // reference declaration |
| << FixIt; |
| } else if (R.getAsSingle<EnumConstantDecl>()) { |
| // Don't provide a fixit outside C++11 mode; we don't want to suggest |
| // repeating the type of the enumeration here, and we can't do so if |
| // the type is anonymous. |
| FixItHint FixIt; |
| if (getLangOpts().CPlusPlus11) { |
| // Convert 'using X::Y;' to 'auto &Y = X::Y;'. |
| FixIt = FixItHint::CreateReplacement( |
| UsingLoc, |
| "constexpr auto " + NameInfo.getName().getAsString() + " = "); |
| } |
| |
| Diag(UsingLoc, diag::note_using_decl_class_member_workaround) |
| << (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable |
| << FixIt; |
| } |
| return true; |
| } |
| |
| // Otherwise, this might be valid. |
| return false; |
| } |
| |
| // The current scope is a record. |
| |
| // If the named context is dependent, we can't decide much. |
| if (!NamedContext) { |
| // FIXME: in C++0x, we can diagnose if we can prove that the |
| // nested-name-specifier does not refer to a base class, which is |
| // still possible in some cases. |
| |
| // Otherwise we have to conservatively report that things might be |
| // okay. |
| return false; |
| } |
| |
| if (!NamedContext->isRecord()) { |
| // Ideally this would point at the last name in the specifier, |
| // but we don't have that level of source info. |
| Diag(SS.getRange().getBegin(), |
| diag::err_using_decl_nested_name_specifier_is_not_class) |
| << SS.getScopeRep() << SS.getRange(); |
| return true; |
| } |
| |
| if (!NamedContext->isDependentContext() && |
| RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext)) |
| return true; |
| |
| if (getLangOpts().CPlusPlus11) { |
| // C++11 [namespace.udecl]p3: |
| // In a using-declaration used as a member-declaration, the |
| // nested-name-specifier shall name a base class of the class |
| // being defined. |
| |
| if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom( |
| cast<CXXRecordDecl>(NamedContext))) { |
| if (CurContext == NamedContext) { |
| Diag(NameLoc, |
| diag::err_using_decl_nested_name_specifier_is_current_class) |
| << SS.getRange(); |
| return true; |
| } |
| |
| if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) { |
| Diag(SS.getRange().getBegin(), |
| diag::err_using_decl_nested_name_specifier_is_not_base_class) |
| << SS.getScopeRep() |
| << cast<CXXRecordDecl>(CurContext) |
| << SS.getRange(); |
| } |
| return true; |
| } |
| |
| return false; |
| } |
| |
| // C++03 [namespace.udecl]p4: |
| // A using-declaration used as a member-declaration shall refer |
| // to a member of a base class of the class being defined [etc.]. |
| |
| // Salient point: SS doesn't have to name a base class as long as |
| // lookup only finds members from base classes. Therefore we can |
| // diagnose here only if we can prove that that can't happen, |
| // i.e. if the class hierarchies provably don't intersect. |
| |
| // TODO: it would be nice if "definitely valid" results were cached |
| // in the UsingDecl and UsingShadowDecl so that these checks didn't |
| // need to be repeated. |
| |
| llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases; |
| auto Collect = [&Bases](const CXXRecordDecl *Base) { |
| Bases.insert(Base); |
| return true; |
| }; |
| |
| // Collect all bases. Return false if we find a dependent base. |
| if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect)) |
| return false; |
| |
| // Returns true if the base is dependent or is one of the accumulated base |
| // classes. |
| auto IsNotBase = [&Bases](const CXXRecordDecl *Base) { |
| return !Bases.count(Base); |
| }; |
| |
| // Return false if the class has a dependent base or if it or one |
| // of its bases is present in the base set of the current context. |
| if (Bases.count(cast<CXXRecordDecl>(NamedContext)) || |
| !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase)) |
| return false; |
| |
| Diag(SS.getRange().getBegin(), |
| diag::err_using_decl_nested_name_specifier_is_not_base_class) |
| << SS.getScopeRep() |
| << cast<CXXRecordDecl>(CurContext) |
| << SS.getRange(); |
| |
| return true; |
| } |
| |
| Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, |
| MultiTemplateParamsArg TemplateParamLists, |
| SourceLocation UsingLoc, UnqualifiedId &Name, |
| const ParsedAttributesView &AttrList, |
| TypeResult Type, Decl *DeclFromDeclSpec) { |
| // Skip up to the relevant declaration scope. |
| while (S->isTemplateParamScope()) |
| S = S->getParent(); |
| assert((S->getFlags() & Scope::DeclScope) && |
| "got alias-declaration outside of declaration scope"); |
| |
| if (Type.isInvalid()) |
| return nullptr; |
| |
| bool Invalid = false; |
| DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); |
| TypeSourceInfo *TInfo = nullptr; |
| GetTypeFromParser(Type.get(), &TInfo); |
| |
| if (DiagnoseClassNameShadow(CurContext, NameInfo)) |
| return nullptr; |
| |
| if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, |
| UPPC_DeclarationType)) { |
| Invalid = true; |
| TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, |
| TInfo->getTypeLoc().getBeginLoc()); |
| } |
| |
| LookupResult Previous(*this, NameInfo, LookupOrdinaryName, |
| TemplateParamLists.size() |
| ? forRedeclarationInCurContext() |
| : ForVisibleRedeclaration); |
| LookupName(Previous, S); |
| |
| // Warn about shadowing the name of a template parameter. |
| if (Previous.isSingleResult() && |
| Previous.getFoundDecl()->isTemplateParameter()) { |
| DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl()); |
| Previous.clear(); |
| } |
| |
| assert(Name.Kind == UnqualifiedIdKind::IK_Identifier && |
| "name in alias declaration must be an identifier"); |
| TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, |
| Name.StartLocation, |
| Name.Identifier, TInfo); |
| |
| NewTD->setAccess(AS); |
| |
| if (Invalid) |
| NewTD->setInvalidDecl(); |
| |
| ProcessDeclAttributeList(S, NewTD, AttrList); |
| AddPragmaAttributes(S, NewTD); |
| |
| CheckTypedefForVariablyModifiedType(S, NewTD); |
| Invalid |= NewTD->isInvalidDecl(); |
| |
| bool Redeclaration = false; |
| |
| NamedDecl *NewND; |
| if (TemplateParamLists.size()) { |
| TypeAliasTemplateDecl *OldDecl = nullptr; |
| TemplateParameterList *OldTemplateParams = nullptr; |
| |
| if (TemplateParamLists.size() != 1) { |
| Diag(UsingLoc, diag::err_alias_template_extra_headers) |
| << SourceRange(TemplateParamLists[1]->getTemplateLoc(), |
| TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc()); |
| } |
| TemplateParameterList *TemplateParams = TemplateParamLists[0]; |
| |
| // Check that we can declare a template here. |
| if (CheckTemplateDeclScope(S, TemplateParams)) |
| return nullptr; |
| |
| // Only consider previous declarations in the same scope. |
| FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false, |
| /*ExplicitInstantiationOrSpecialization*/false); |
| if (!Previous.empty()) { |
| Redeclaration = true; |
| |
| OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>(); |
| if (!OldDecl && !Invalid) { |
| Diag(UsingLoc, diag::err_redefinition_different_kind) |
| << Name.Identifier; |
| |
| NamedDecl *OldD = Previous.getRepresentativeDecl(); |
| if (OldD->getLocation().isValid()) |
| Diag(OldD->getLocation(), diag::note_previous_definition); |
| |
| Invalid = true; |
| } |
| |
| if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) { |
| if (TemplateParameterListsAreEqual(TemplateParams, |
| OldDecl->getTemplateParameters(), |
| /*Complain=*/true, |
| TPL_TemplateMatch)) |
| OldTemplateParams = OldDecl->getTemplateParameters(); |
| else |
| Invalid = true; |
| |
| TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl(); |
| if (!Invalid && |
| !Context.hasSameType(OldTD->getUnderlyingType(), |
| NewTD->getUnderlyingType())) { |
| // FIXME: The C++0x standard does not clearly say this is ill-formed, |
| // but we can't reasonably accept it. |
| Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef) |
| << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType(); |
| if (OldTD->getLocation().isValid()) |
| Diag(OldTD->getLocation(), diag::note_previous_definition); |
| Invalid = true; |
| } |
| } |
| } |
| |
| // Merge any previous default template arguments into our parameters, |
| // and check the parameter list. |
| if (CheckTemplateParameterList(TemplateParams, OldTemplateParams, |
| TPC_TypeAliasTemplate)) |
| return nullptr; |
| |
| TypeAliasTemplateDecl *NewDecl = |
| TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc, |
| Name.Identifier, TemplateParams, |
| NewTD); |
| NewTD->setDescribedAliasTemplate(NewDecl); |
| |
| NewDecl->setAccess(AS); |
| |
| if (Invalid) |
| NewDecl->setInvalidDecl(); |
| else if (OldDecl) { |
| NewDecl->setPreviousDecl(OldDecl); |
| CheckRedeclarationModuleOwnership(NewDecl, OldDecl); |
| } |
| |
| NewND = NewDecl; |
| } else { |
| if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) { |
| setTagNameForLinkagePurposes(TD, NewTD); |
| handleTagNumbering(TD, S); |
| } |
| ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); |
| NewND = NewTD; |
| } |
| |
| PushOnScopeChains(NewND, S); |
| ActOnDocumentableDecl(NewND); |
| return NewND; |
| } |
| |
| Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, |
| SourceLocation AliasLoc, |
| IdentifierInfo *Alias, CXXScopeSpec &SS, |
| SourceLocation IdentLoc, |
| IdentifierInfo *Ident) { |
| |
| // Lookup the namespace name. |
| LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName); |
| LookupParsedName(R, S, &SS); |
| |
| if (R.isAmbiguous()) |
| return nullptr; |
| |
| if (R.empty()) { |
| if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { |
| Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange(); |
| return nullptr; |
| } |
| } |
| assert(!R.isAmbiguous() && !R.empty()); |
| NamedDecl *ND = R.getRepresentativeDecl(); |
| |
| // Check if we have a previous declaration with the same name. |
| LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName, |
| ForVisibleRedeclaration); |
| LookupName(PrevR, S); |
| |
| // Check we're not shadowing a template parameter. |
| if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) { |
| DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl()); |
| PrevR.clear(); |
| } |
| |
| // Filter out any other lookup result from an enclosing scope. |
| FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false, |
| /*AllowInlineNamespace*/false); |
| |
| // Find the previous declaration and check that we can redeclare it. |
| NamespaceAliasDecl *Prev = nullptr; |
| if (PrevR.isSingleResult()) { |
| NamedDecl *PrevDecl = PrevR.getRepresentativeDecl(); |
| if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) { |
| // We already have an alias with the same name that points to the same |
| // namespace; check that it matches. |
| if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) { |
| Prev = AD; |
| } else if (isVisible(PrevDecl)) { |
| Diag(AliasLoc, diag::err_redefinition_different_namespace_alias) |
| << Alias; |
| Diag(AD->getLocation(), diag::note_previous_namespace_alias) |
| << AD->getNamespace(); |
| return nullptr; |
| } |
| } else if (isVisible(PrevDecl)) { |
| unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl()) |
| ? diag::err_redefinition |
| : diag::err_redefinition_different_kind; |
| Diag(AliasLoc, DiagID) << Alias; |
| Diag(PrevDecl->getLocation(), diag::note_previous_definition); |
| return nullptr; |
| } |
| } |
| |
| // The use of a nested name specifier may trigger deprecation warnings. |
| DiagnoseUseOfDecl(ND, IdentLoc); |
| |
| NamespaceAliasDecl *AliasDecl = |
| NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc, |
| Alias, SS.getWithLocInContext(Context), |
| IdentLoc, ND); |
| if (Prev) |
| AliasDecl->setPreviousDecl(Prev); |
| |
| PushOnScopeChains(AliasDecl, S); |
| return AliasDecl; |
| } |
| |
| namespace { |
| struct SpecialMemberExceptionSpecInfo |
| : SpecialMemberVisitor<SpecialMemberExceptionSpecInfo> { |
| SourceLocation Loc; |
| Sema::ImplicitExceptionSpecification ExceptSpec; |
| |
| SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD, |
| Sema::CXXSpecialMember CSM, |
| Sema::InheritedConstructorInfo *ICI, |
| SourceLocation Loc) |
| : SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {} |
| |
| bool visitBase(CXXBaseSpecifier *Base); |
| bool visitField(FieldDecl *FD); |
| |
| void visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj, |
| unsigned Quals); |
| |
| void visitSubobjectCall(Subobject Subobj, |
| Sema::SpecialMemberOverloadResult SMOR); |
| }; |
| } |
| |
| bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) { |
| auto *RT = Base->getType()->getAs<RecordType>(); |
| if (!RT) |
| return false; |
| |
| auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl()); |
| Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass); |
| if (auto *BaseCtor = SMOR.getMethod()) { |
| visitSubobjectCall(Base, BaseCtor); |
| return false; |
| } |
| |
| visitClassSubobject(BaseClass, Base, 0); |
| return false; |
| } |
| |
| bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) { |
| if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) { |
| Expr *E = FD->getInClassInitializer(); |
| if (!E) |
| // FIXME: It's a little wasteful to build and throw away a |
| // CXXDefaultInitExpr here. |
| // FIXME: We should have a single context note pointing at Loc, and |
| // this location should be MD->getLocation() instead, since that's |
| // the location where we actually use the default init expression. |
| E = S.BuildCXXDefaultInitExpr(Loc, FD).get(); |
| if (E) |
| ExceptSpec.CalledExpr(E); |
| } else if (auto *RT = S.Context.getBaseElementType(FD->getType()) |
| ->getAs<RecordType>()) { |
| visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD, |
| FD->getType().getCVRQualifiers()); |
| } |
| return false; |
| } |
| |
| void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class, |
| Subobject Subobj, |
| unsigned Quals) { |
| FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>(); |
| bool IsMutable = Field && Field->isMutable(); |
| visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable)); |
| } |
| |
| void SpecialMemberExceptionSpecInfo::visitSubobjectCall( |
| Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR) { |
| // Note, if lookup fails, it doesn't matter what exception specification we |
| // choose because the special member will be deleted. |
| if (CXXMethodDecl *MD = SMOR.getMethod()) |
| ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD); |
| } |
| |
| static Sema::ImplicitExceptionSpecification |
| ComputeDefaultedSpecialMemberExceptionSpec( |
| Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM, |
| Sema::InheritedConstructorInfo *ICI) { |
| CXXRecordDecl *ClassDecl = MD->getParent(); |
| |
| // C++ [except.spec]p14: |
| // An implicitly declared special member function (Clause 12) shall have an |
| // exception-specification. [...] |
| SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, Loc); |
| if (ClassDecl->isInvalidDecl()) |
| return Info.ExceptSpec; |
| |
| // C++1z [except.spec]p7: |
| // [Look for exceptions thrown by] a constructor selected [...] to |
| // initialize a potentially constructed subobject, |
| // C++1z [except.spec]p8: |
| // The exception specification for an implicitly-declared destructor, or a |
| // destructor without a noexcept-specifier, is potentially-throwing if and |
| // only if any of the destructors for any of its potentially constructed |
| // subojects is potentially throwing. |
| // FIXME: We respect the first rule but ignore the "potentially constructed" |
| // in the second rule to resolve a core issue (no number yet) that would have |
| // us reject: |
| // struct A { virtual void f() = 0; virtual ~A() noexcept(false) = 0; }; |
| // struct B : A {}; |
| // struct C : B { void f(); }; |
| // ... due to giving B::~B() a non-throwing exception specification. |
| Info.visit(Info.IsConstructor ? Info.VisitPotentiallyConstructedBases |
| : Info.VisitAllBases); |
| |
| return Info.ExceptSpec; |
| } |
| |
| namespace { |
| /// RAII object to register a special member as being currently declared. |
| struct DeclaringSpecialMember { |
| Sema &S; |
| Sema::SpecialMemberDecl D; |
| Sema::ContextRAII SavedContext; |
| bool WasAlreadyBeingDeclared; |
| |
| DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM) |
| : S(S), D(RD, CSM), SavedContext(S, RD) { |
| WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second; |
| if (WasAlreadyBeingDeclared) |
| // This almost never happens, but if it does, ensure that our cache |
| // doesn't contain a stale result. |
| S.SpecialMemberCache.clear(); |
| else { |
| // Register a note to be produced if we encounter an error while |
| // declaring the special member. |
| Sema::CodeSynthesisContext Ctx; |
| Ctx.Kind = Sema::CodeSynthesisContext::DeclaringSpecialMember; |
| // FIXME: We don't have a location to use here. Using the class's |
| // location maintains the fiction that we declare all special members |
| // with the class, but (1) it's not clear that lying about that helps our |
| // users understand what's going on, and (2) there may be outer contexts |
| // on the stack (some of which are relevant) and printing them exposes |
| // our lies. |
| Ctx.PointOfInstantiation = RD->getLocation(); |
| Ctx.Entity = RD; |
| Ctx.SpecialMember = CSM; |
| S.pushCodeSynthesisContext(Ctx); |
| } |
| } |
| ~DeclaringSpecialMember() { |
| if (!WasAlreadyBeingDeclared) { |
| S.SpecialMembersBeingDeclared.erase(D); |
| S.popCodeSynthesisContext(); |
| } |
| } |
| |
| /// Are we already trying to declare this special member? |
| bool isAlreadyBeingDeclared() const { |
| return WasAlreadyBeingDeclared; |
| } |
| }; |
| } |
| |
| void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) { |
| // Look up any existing declarations, but don't trigger declaration of all |
| // implicit special members with this name. |
| DeclarationName Name = FD->getDeclName(); |
| LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName, |
| ForExternalRedeclaration); |
| for (auto *D : FD->getParent()->lookup(Name)) |
| if (auto *Acceptable = R.getAcceptableDecl(D)) |
| R.addDecl(Acceptable); |
| R.resolveKind(); |
| R.suppressDiagnostics(); |
| |
| CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false); |
| } |
| |
| CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( |
| CXXRecordDecl *ClassDecl) { |
| // C++ [class.ctor]p5: |
| // A default constructor for a class X is a constructor of class X |
| // that can be called without an argument. If there is no |
| // user-declared constructor for class X, a default constructor is |
| // implicitly declared. An implicitly-declared default constructor |
| // is an inline public member of its class. |
| assert(ClassDecl->needsImplicitDefaultConstructor() && |
| "Should not build implicit default constructor!"); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, |
| CXXDefaultConstructor, |
| false); |
| |
| // Create the actual constructor declaration. |
| CanQualType ClassType |
| = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationName Name |
| = Context.DeclarationNames.getCXXConstructorName(ClassType); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( |
| Context, ClassDecl, ClassLoc, NameInfo, /*Type*/QualType(), |
| /*TInfo=*/nullptr, /*isExplicit=*/false, /*isInline=*/true, |
| /*isImplicitlyDeclared=*/true, Constexpr); |
| DefaultCon->setAccess(AS_public); |
| DefaultCon->setDefaulted(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor, |
| DefaultCon, |
| /* ConstRHS */ false, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this constructor. |
| FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon); |
| DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); |
| |
| // We don't need to use SpecialMemberIsTrivial here; triviality for default |
| // constructors is easy to compute. |
| DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor()); |
| |
| // Note that we have declared this constructor. |
| ++ASTContext::NumImplicitDefaultConstructorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, DefaultCon); |
| |
| if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor)) |
| SetDeclDeleted(DefaultCon, ClassLoc); |
| |
| if (S) |
| PushOnScopeChains(DefaultCon, S, false); |
| ClassDecl->addDecl(DefaultCon); |
| |
| return DefaultCon; |
| } |
| |
| void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, |
| CXXConstructorDecl *Constructor) { |
| assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() && |
| !Constructor->doesThisDeclarationHaveABody() && |
| !Constructor->isDeleted()) && |
| "DefineImplicitDefaultConstructor - call it for implicit default ctor"); |
| if (Constructor->willHaveBody() || Constructor->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = Constructor->getParent(); |
| assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); |
| |
| SynthesizedFunctionScope Scope(*this, Constructor); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| Constructor->getType()->castAs<FunctionProtoType>()); |
| MarkVTableUsed(CurrentLocation, ClassDecl); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| if (SetCtorInitializers(Constructor, /*AnyErrors=*/false)) { |
| Constructor->setInvalidDecl(); |
| return; |
| } |
| |
| SourceLocation Loc = Constructor->getLocEnd().isValid() |
| ? Constructor->getLocEnd() |
| : Constructor->getLocation(); |
| Constructor->setBody(new (Context) CompoundStmt(Loc)); |
| Constructor->markUsed(Context); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(Constructor); |
| } |
| |
| DiagnoseUninitializedFields(*this, Constructor); |
| } |
| |
| void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { |
| // Perform any delayed checks on exception specifications. |
| CheckDelayedMemberExceptionSpecs(); |
| } |
| |
| /// Find or create the fake constructor we synthesize to model constructing an |
| /// object of a derived class via a constructor of a base class. |
| CXXConstructorDecl * |
| Sema::findInheritingConstructor(SourceLocation Loc, |
| CXXConstructorDecl *BaseCtor, |
| ConstructorUsingShadowDecl *Shadow) { |
| CXXRecordDecl *Derived = Shadow->getParent(); |
| SourceLocation UsingLoc = Shadow->getLocation(); |
| |
| // FIXME: Add a new kind of DeclarationName for an inherited constructor. |
| // For now we use the name of the base class constructor as a member of the |
| // derived class to indicate a (fake) inherited constructor name. |
| DeclarationName Name = BaseCtor->getDeclName(); |
| |
| // Check to see if we already have a fake constructor for this inherited |
| // constructor call. |
| for (NamedDecl *Ctor : Derived->lookup(Name)) |
| if (declaresSameEntity(cast<CXXConstructorDecl>(Ctor) |
| ->getInheritedConstructor() |
| .getConstructor(), |
| BaseCtor)) |
| return cast<CXXConstructorDecl>(Ctor); |
| |
| DeclarationNameInfo NameInfo(Name, UsingLoc); |
| TypeSourceInfo *TInfo = |
| Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc); |
| FunctionProtoTypeLoc ProtoLoc = |
| TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>(); |
| |
| // Check the inherited constructor is valid and find the list of base classes |
| // from which it was inherited. |
| InheritedConstructorInfo ICI(*this, Loc, Shadow); |
| |
| bool Constexpr = |
| BaseCtor->isConstexpr() && |
| defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor, |
| false, BaseCtor, &ICI); |
| |
| CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( |
| Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, |
| BaseCtor->isExplicit(), /*Inline=*/true, |
| /*ImplicitlyDeclared=*/true, Constexpr, |
| InheritedConstructor(Shadow, BaseCtor)); |
| if (Shadow->isInvalidDecl()) |
| DerivedCtor->setInvalidDecl(); |
| |
| // Build an unevaluated exception specification for this fake constructor. |
| const FunctionProtoType *FPT = TInfo->getType()->castAs<FunctionProtoType>(); |
| FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); |
| EPI.ExceptionSpec.Type = EST_Unevaluated; |
| EPI.ExceptionSpec.SourceDecl = DerivedCtor; |
| DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(), |
| FPT->getParamTypes(), EPI)); |
| |
| // Build the parameter declarations. |
| SmallVector<ParmVarDecl *, 16> ParamDecls; |
| for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) { |
| TypeSourceInfo *TInfo = |
| Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc); |
| ParmVarDecl *PD = ParmVarDecl::Create( |
| Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr, |
| FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr); |
| PD->setScopeInfo(0, I); |
| PD->setImplicit(); |
| // Ensure attributes are propagated onto parameters (this matters for |
| // format, pass_object_size, ...). |
| mergeDeclAttributes(PD, BaseCtor->getParamDecl(I)); |
| ParamDecls.push_back(PD); |
| ProtoLoc.setParam(I, PD); |
| } |
| |
| // Set up the new constructor. |
| assert(!BaseCtor->isDeleted() && "should not use deleted constructor"); |
| DerivedCtor->setAccess(BaseCtor->getAccess()); |
| DerivedCtor->setParams(ParamDecls); |
| Derived->addDecl(DerivedCtor); |
| |
| if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI)) |
| SetDeclDeleted(DerivedCtor, UsingLoc); |
| |
| return DerivedCtor; |
| } |
| |
| void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) { |
| InheritedConstructorInfo ICI(*this, Ctor->getLocation(), |
| Ctor->getInheritedConstructor().getShadowDecl()); |
| ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI, |
| /*Diagnose*/true); |
| } |
| |
| void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, |
| CXXConstructorDecl *Constructor) { |
| CXXRecordDecl *ClassDecl = Constructor->getParent(); |
| assert(Constructor->getInheritedConstructor() && |
| !Constructor->doesThisDeclarationHaveABody() && |
| !Constructor->isDeleted()); |
| if (Constructor->willHaveBody() || Constructor->isInvalidDecl()) |
| return; |
| |
| // Initializations are performed "as if by a defaulted default constructor", |
| // so enter the appropriate scope. |
| SynthesizedFunctionScope Scope(*this, Constructor); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| Constructor->getType()->castAs<FunctionProtoType>()); |
| MarkVTableUsed(CurrentLocation, ClassDecl); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| ConstructorUsingShadowDecl *Shadow = |
| Constructor->getInheritedConstructor().getShadowDecl(); |
| CXXConstructorDecl *InheritedCtor = |
| Constructor->getInheritedConstructor().getConstructor(); |
| |
| // [class.inhctor.init]p1: |
| // initialization proceeds as if a defaulted default constructor is used to |
| // initialize the D object and each base class subobject from which the |
| // constructor was inherited |
| |
| InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow); |
| CXXRecordDecl *RD = Shadow->getParent(); |
| SourceLocation InitLoc = Shadow->getLocation(); |
| |
| // Build explicit initializers for all base classes from which the |
| // constructor was inherited. |
| SmallVector<CXXCtorInitializer*, 8> Inits; |
| for (bool VBase : {false, true}) { |
| for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) { |
| if (B.isVirtual() != VBase) |
| continue; |
| |
| auto *BaseRD = B.getType()->getAsCXXRecordDecl(); |
| if (!BaseRD) |
| continue; |
| |
| auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor); |
| if (!BaseCtor.first) |
| continue; |
| |
| MarkFunctionReferenced(CurrentLocation, BaseCtor.first); |
| ExprResult Init = new (Context) CXXInheritedCtorInitExpr( |
| InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second); |
| |
| auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(), InitLoc); |
| Inits.push_back(new (Context) CXXCtorInitializer( |
| Context, TInfo, VBase, InitLoc, Init.get(), InitLoc, |
| SourceLocation())); |
| } |
| } |
| |
| // We now proceed as if for a defaulted default constructor, with the relevant |
| // initializers replaced. |
| |
| if (SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits)) { |
| Constructor->setInvalidDecl(); |
| return; |
| } |
| |
| Constructor->setBody(new (Context) CompoundStmt(InitLoc)); |
| Constructor->markUsed(Context); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(Constructor); |
| } |
| |
| DiagnoseUninitializedFields(*this, Constructor); |
| } |
| |
| CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) { |
| // C++ [class.dtor]p2: |
| // If a class has no user-declared destructor, a destructor is |
| // declared implicitly. An implicitly-declared destructor is an |
| // inline public member of its class. |
| assert(ClassDecl->needsImplicitDestructor()); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| // Create the actual destructor declaration. |
| CanQualType ClassType |
| = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl)); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationName Name |
| = Context.DeclarationNames.getCXXDestructorName(ClassType); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| CXXDestructorDecl *Destructor |
| = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, |
| QualType(), nullptr, /*isInline=*/true, |
| /*isImplicitlyDeclared=*/true); |
| Destructor->setAccess(AS_public); |
| Destructor->setDefaulted(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor, |
| Destructor, |
| /* ConstRHS */ false, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this destructor. |
| FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor); |
| Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); |
| |
| // We don't need to use SpecialMemberIsTrivial here; triviality for |
| // destructors is easy to compute. |
| Destructor->setTrivial(ClassDecl->hasTrivialDestructor()); |
| Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() || |
| ClassDecl->hasTrivialDestructorForCall()); |
| |
| // Note that we have declared this destructor. |
| ++ASTContext::NumImplicitDestructorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, Destructor); |
| |
| // We can't check whether an implicit destructor is deleted before we complete |
| // the definition of the class, because its validity depends on the alignment |
| // of the class. We'll check this from ActOnFields once the class is complete. |
| if (ClassDecl->isCompleteDefinition() && |
| ShouldDeleteSpecialMember(Destructor, CXXDestructor)) |
| SetDeclDeleted(Destructor, ClassLoc); |
| |
| // Introduce this destructor into its scope. |
| if (S) |
| PushOnScopeChains(Destructor, S, false); |
| ClassDecl->addDecl(Destructor); |
| |
| return Destructor; |
| } |
| |
| void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, |
| CXXDestructorDecl *Destructor) { |
| assert((Destructor->isDefaulted() && |
| !Destructor->doesThisDeclarationHaveABody() && |
| !Destructor->isDeleted()) && |
| "DefineImplicitDestructor - call it for implicit default dtor"); |
| if (Destructor->willHaveBody() || Destructor->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = Destructor->getParent(); |
| assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); |
| |
| SynthesizedFunctionScope Scope(*this, Destructor); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| Destructor->getType()->castAs<FunctionProtoType>()); |
| MarkVTableUsed(CurrentLocation, ClassDecl); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), |
| Destructor->getParent()); |
| |
| if (CheckDestructor(Destructor)) { |
| Destructor->setInvalidDecl(); |
| return; |
| } |
| |
| SourceLocation Loc = Destructor->getLocEnd().isValid() |
| ? Destructor->getLocEnd() |
| : Destructor->getLocation(); |
| Destructor->setBody(new (Context) CompoundStmt(Loc)); |
| Destructor->markUsed(Context); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(Destructor); |
| } |
| } |
| |
| /// Perform any semantic analysis which needs to be delayed until all |
| /// pending class member declarations have been parsed. |
| void Sema::ActOnFinishCXXMemberDecls() { |
| // If the context is an invalid C++ class, just suppress these checks. |
| if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { |
| if (Record->isInvalidDecl()) { |
| DelayedDefaultedMemberExceptionSpecs.clear(); |
| DelayedExceptionSpecChecks.clear(); |
| return; |
| } |
| checkForMultipleExportedDefaultConstructors(*this, Record); |
| } |
| } |
| |
| void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { |
| referenceDLLExportedClassMethods(); |
| } |
| |
| void Sema::referenceDLLExportedClassMethods() { |
| if (!DelayedDllExportClasses.empty()) { |
| // Calling ReferenceDllExportedMembers might cause the current function to |
| // be called again, so use a local copy of DelayedDllExportClasses. |
| SmallVector<CXXRecordDecl *, 4> WorkList; |
| std::swap(DelayedDllExportClasses, WorkList); |
| for (CXXRecordDecl *Class : WorkList) |
| ReferenceDllExportedMembers(*this, Class); |
| } |
| } |
| |
| void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, |
| CXXDestructorDecl *Destructor) { |
| assert(getLangOpts().CPlusPlus11 && |
| "adjusting dtor exception specs was introduced in c++11"); |
| |
| // C++11 [class.dtor]p3: |
| // A declaration of a destructor that does not have an exception- |
| // specification is implicitly considered to have the same exception- |
| // specification as an implicit declaration. |
| const FunctionProtoType *DtorType = Destructor->getType()-> |
| getAs<FunctionProtoType>(); |
| if (DtorType->hasExceptionSpec()) |
| return; |
| |
| // Replace the destructor's type, building off the existing one. Fortunately, |
| // the only thing of interest in the destructor type is its extended info. |
| // The return and arguments are fixed. |
| FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo(); |
| EPI.ExceptionSpec.Type = EST_Unevaluated; |
| EPI.ExceptionSpec.SourceDecl = Destructor; |
| Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI)); |
| |
| // FIXME: If the destructor has a body that could throw, and the newly created |
| // spec doesn't allow exceptions, we should emit a warning, because this |
| // change in behavior can break conforming C++03 programs at runtime. |
| // However, we don't have a body or an exception specification yet, so it |
| // needs to be done somewhere else. |
| } |
| |
| namespace { |
| /// An abstract base class for all helper classes used in building the |
| // copy/move operators. These classes serve as factory functions and help us |
| // avoid using the same Expr* in the AST twice. |
| class ExprBuilder { |
| ExprBuilder(const ExprBuilder&) = delete; |
| ExprBuilder &operator=(const ExprBuilder&) = delete; |
| |
| protected: |
| static Expr *assertNotNull(Expr *E) { |
| assert(E && "Expression construction must not fail."); |
| return E; |
| } |
| |
| public: |
| ExprBuilder() {} |
| virtual ~ExprBuilder() {} |
| |
| virtual Expr *build(Sema &S, SourceLocation Loc) const = 0; |
| }; |
| |
| class RefBuilder: public ExprBuilder { |
| VarDecl *Var; |
| QualType VarType; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get()); |
| } |
| |
| RefBuilder(VarDecl *Var, QualType VarType) |
| : Var(Var), VarType(VarType) {} |
| }; |
| |
| class ThisBuilder: public ExprBuilder { |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(S.ActOnCXXThis(Loc).getAs<Expr>()); |
| } |
| }; |
| |
| class CastBuilder: public ExprBuilder { |
| const ExprBuilder &Builder; |
| QualType Type; |
| ExprValueKind Kind; |
| const CXXCastPath &Path; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type, |
| CK_UncheckedDerivedToBase, Kind, |
| &Path).get()); |
| } |
| |
| CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind, |
| const CXXCastPath &Path) |
| : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {} |
| }; |
| |
| class DerefBuilder: public ExprBuilder { |
| const ExprBuilder &Builder; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull( |
| S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get()); |
| } |
| |
| DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {} |
| }; |
| |
| class MemberBuilder: public ExprBuilder { |
| const ExprBuilder &Builder; |
| QualType Type; |
| CXXScopeSpec SS; |
| bool IsArrow; |
| LookupResult &MemberLookup; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(S.BuildMemberReferenceExpr( |
| Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(), |
| nullptr, MemberLookup, nullptr, nullptr).get()); |
| } |
| |
| MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow, |
| LookupResult &MemberLookup) |
| : Builder(Builder), Type(Type), IsArrow(IsArrow), |
| MemberLookup(MemberLookup) {} |
| }; |
| |
| class MoveCastBuilder: public ExprBuilder { |
| const ExprBuilder &Builder; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(CastForMoving(S, Builder.build(S, Loc))); |
| } |
| |
| MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {} |
| }; |
| |
| class LvalueConvBuilder: public ExprBuilder { |
| const ExprBuilder &Builder; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull( |
| S.DefaultLvalueConversion(Builder.build(S, Loc)).get()); |
| } |
| |
| LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {} |
| }; |
| |
| class SubscriptBuilder: public ExprBuilder { |
| const ExprBuilder &Base; |
| const ExprBuilder &Index; |
| |
| public: |
| Expr *build(Sema &S, SourceLocation Loc) const override { |
| return assertNotNull(S.CreateBuiltinArraySubscriptExpr( |
| Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get()); |
| } |
| |
| SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index) |
| : Base(Base), Index(Index) {} |
| }; |
| |
| } // end anonymous namespace |
| |
| /// When generating a defaulted copy or move assignment operator, if a field |
| /// should be copied with __builtin_memcpy rather than via explicit assignments, |
| /// do so. This optimization only applies for arrays of scalars, and for arrays |
| /// of class type where the selected copy/move-assignment operator is trivial. |
| static StmtResult |
| buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, |
| const ExprBuilder &ToB, const ExprBuilder &FromB) { |
| // Compute the size of the memory buffer to be copied. |
| QualType SizeType = S.Context.getSizeType(); |
| llvm::APInt Size(S.Context.getTypeSize(SizeType), |
| S.Context.getTypeSizeInChars(T).getQuantity()); |
| |
| // Take the address of the field references for "from" and "to". We |
| // directly construct UnaryOperators here because semantic analysis |
| // does not permit us to take the address of an xvalue. |
| Expr *From = FromB.build(S, Loc); |
| From = new (S.Context) UnaryOperator(From, UO_AddrOf, |
| S.Context.getPointerType(From->getType()), |
| VK_RValue, OK_Ordinary, Loc, false); |
| Expr *To = ToB.build(S, Loc); |
| To = new (S.Context) UnaryOperator(To, UO_AddrOf, |
| S.Context.getPointerType(To->getType()), |
| VK_RValue, OK_Ordinary, Loc, false); |
| |
| const Type *E = T->getBaseElementTypeUnsafe(); |
| bool NeedsCollectableMemCpy = |
| E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember(); |
| |
| // Create a reference to the __builtin_objc_memmove_collectable function |
| StringRef MemCpyName = NeedsCollectableMemCpy ? |
| "__builtin_objc_memmove_collectable" : |
| "__builtin_memcpy"; |
| LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc, |
| Sema::LookupOrdinaryName); |
| S.LookupName(R, S.TUScope, true); |
| |
| FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>(); |
| if (!MemCpy) |
| // Something went horribly wrong earlier, and we will have complained |
| // about it. |
| return StmtError(); |
| |
| ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy, |
| VK_RValue, Loc, nullptr); |
| assert(MemCpyRef.isUsable() && "Builtin reference cannot fail"); |
| |
| Expr *CallArgs[] = { |
| To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc) |
| }; |
| ExprResult Call = S.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.get(), |
| Loc, CallArgs, Loc); |
| |
| assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!"); |
| return Call.getAs<Stmt>(); |
| } |
| |
| /// Builds a statement that copies/moves the given entity from \p From to |
| /// \c To. |
| /// |
| /// This routine is used to copy/move the members of a class with an |
| /// implicitly-declared copy/move assignment operator. When the entities being |
| /// copied are arrays, this routine builds for loops to copy them. |
| /// |
| /// \param S The Sema object used for type-checking. |
| /// |
| /// \param Loc The location where the implicit copy/move is being generated. |
| /// |
| /// \param T The type of the expressions being copied/moved. Both expressions |
| /// must have this type. |
| /// |
| /// \param To The expression we are copying/moving to. |
| /// |
| /// \param From The expression we are copying/moving from. |
| /// |
| /// \param CopyingBaseSubobject Whether we're copying/moving a base subobject. |
| /// Otherwise, it's a non-static member subobject. |
| /// |
| /// \param Copying Whether we're copying or moving. |
| /// |
| /// \param Depth Internal parameter recording the depth of the recursion. |
| /// |
| /// \returns A statement or a loop that copies the expressions, or StmtResult(0) |
| /// if a memcpy should be used instead. |
| static StmtResult |
| buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T, |
| const ExprBuilder &To, const ExprBuilder &From, |
| bool CopyingBaseSubobject, bool Copying, |
| unsigned Depth = 0) { |
| // C++11 [class.copy]p28: |
| // Each subobject is assigned in the manner appropriate to its type: |
| // |
| // - if the subobject is of class type, as if by a call to operator= with |
| // the subobject as the object expression and the corresponding |
| // subobject of x as a single function argument (as if by explicit |
| // qualification; that is, ignoring any possible virtual overriding |
| // functions in more derived classes); |
| // |
| // C++03 [class.copy]p13: |
| // - if the subobject is of class type, the copy assignment operator for |
| // the class is used (as if by explicit qualification; that is, |
| // ignoring any possible virtual overriding functions in more derived |
| // classes); |
| if (const RecordType *RecordTy = T->getAs<RecordType>()) { |
| CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl()); |
| |
| // Look for operator=. |
| DeclarationName Name |
| = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal); |
| LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName); |
| S.LookupQualifiedName(OpLookup, ClassDecl, false); |
| |
| // Prior to C++11, filter out any result that isn't a copy/move-assignment |
| // operator. |
| if (!S.getLangOpts().CPlusPlus11) { |
| LookupResult::Filter F = OpLookup.makeFilter(); |
| while (F.hasNext()) { |
| NamedDecl *D = F.next(); |
| if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) |
| if (Method->isCopyAssignmentOperator() || |
| (!Copying && Method->isMoveAssignmentOperator())) |
| continue; |
| |
| F.erase(); |
| } |
| F.done(); |
| } |
| |
| // Suppress the protected check (C++ [class.protected]) for each of the |
| // assignment operators we found. This strange dance is required when |
| // we're assigning via a base classes's copy-assignment operator. To |
| // ensure that we're getting the right base class subobject (without |
| // ambiguities), we need to cast "this" to that subobject type; to |
| // ensure that we don't go through the virtual call mechanism, we need |
| // to qualify the operator= name with the base class (see below). However, |
| // this means that if the base class has a protected copy assignment |
| // operator, the protected member access check will fail. So, we |
| // rewrite "protected" access to "public" access in this case, since we |
| // know by construction that we're calling from a derived class. |
| if (CopyingBaseSubobject) { |
| for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end(); |
| L != LEnd; ++L) { |
| if (L.getAccess() == AS_protected) |
| L.setAccess(AS_public); |
| } |
| } |
| |
| // Create the nested-name-specifier that will be used to qualify the |
| // reference to operator=; this is required to suppress the virtual |
| // call mechanism. |
| CXXScopeSpec SS; |
| const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr()); |
| SS.MakeTrivial(S.Context, |
| NestedNameSpecifier::Create(S.Context, nullptr, false, |
| CanonicalT), |
| Loc); |
| |
| // Create the reference to operator=. |
| ExprResult OpEqualRef |
| = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false, |
| SS, /*TemplateKWLoc=*/SourceLocation(), |
| /*FirstQualifierInScope=*/nullptr, |
| OpLookup, |
| /*TemplateArgs=*/nullptr, /*S*/nullptr, |
| /*SuppressQualifierCheck=*/true); |
| if (OpEqualRef.isInvalid()) |
| return StmtError(); |
| |
| // Build the call to the assignment operator. |
| |
| Expr *FromInst = From.build(S, Loc); |
| ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr, |
| OpEqualRef.getAs<Expr>(), |
| Loc, FromInst, Loc); |
| if (Call.isInvalid()) |
| return StmtError(); |
| |
| // If we built a call to a trivial 'operator=' while copying an array, |
| // bail out. We'll replace the whole shebang with a memcpy. |
| CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get()); |
| if (CE && CE->getMethodDecl()->isTrivial() && Depth) |
| return StmtResult((Stmt*)nullptr); |
| |
| // Convert to an expression-statement, and clean up any produced |
| // temporaries. |
| return S.ActOnExprStmt(Call); |
| } |
| |
| // - if the subobject is of scalar type, the built-in assignment |
| // operator is used. |
| const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T); |
| if (!ArrayTy) { |
| ExprResult Assignment = S.CreateBuiltinBinOp( |
| Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc)); |
| if (Assignment.isInvalid()) |
| return StmtError(); |
| return S.ActOnExprStmt(Assignment); |
| } |
| |
| // - if the subobject is an array, each element is assigned, in the |
| // manner appropriate to the element type; |
| |
| // Construct a loop over the array bounds, e.g., |
| // |
| // for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0) |
| // |
| // that will copy each of the array elements. |
| QualType SizeType = S.Context.getSizeType(); |
| |
| // Create the iteration variable. |
| IdentifierInfo *IterationVarName = nullptr; |
| { |
| SmallString<8> Str; |
| llvm::raw_svector_ostream OS(Str); |
| OS << "__i" << Depth; |
| IterationVarName = &S.Context.Idents.get(OS.str()); |
| } |
| VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc, |
| IterationVarName, SizeType, |
| S.Context.getTrivialTypeSourceInfo(SizeType, Loc), |
| SC_None); |
| |
| // Initialize the iteration variable to zero. |
| llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0); |
| IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc)); |
| |
| // Creates a reference to the iteration variable. |
| RefBuilder IterationVarRef(IterationVar, SizeType); |
| LvalueConvBuilder IterationVarRefRVal(IterationVarRef); |
| |
| // Create the DeclStmt that holds the iteration variable. |
| Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc); |
| |
| // Subscript the "from" and "to" expressions with the iteration variable. |
| SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal); |
| MoveCastBuilder FromIndexMove(FromIndexCopy); |
| const ExprBuilder *FromIndex; |
| if (Copying) |
| FromIndex = &FromIndexCopy; |
| else |
| FromIndex = &FromIndexMove; |
| |
| SubscriptBuilder ToIndex(To, IterationVarRefRVal); |
| |
| // Build the copy/move for an individual element of the array. |
| StmtResult Copy = |
| buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(), |
| ToIndex, *FromIndex, CopyingBaseSubobject, |
| Copying, Depth + 1); |
| // Bail out if copying fails or if we determined that we should use memcpy. |
| if (Copy.isInvalid() || !Copy.get()) |
| return Copy; |
| |
| // Create the comparison against the array bound. |
| llvm::APInt Upper |
| = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType)); |
| Expr *Comparison |
| = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc), |
| IntegerLiteral::Create(S.Context, Upper, SizeType, Loc), |
| BO_NE, S.Context.BoolTy, |
| VK_RValue, OK_Ordinary, Loc, FPOptions()); |
| |
| // Create the pre-increment of the iteration variable. We can determine |
| // whether the increment will overflow based on the value of the array |
| // bound. |
| Expr *Increment = new (S.Context) |
| UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType, |
| VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue()); |
| |
| // Construct the loop that copies all elements of this array. |
| return S.ActOnForStmt( |
| Loc, Loc, InitStmt, |
| S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean), |
| S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get()); |
| } |
| |
| static StmtResult |
| buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T, |
| const ExprBuilder &To, const ExprBuilder &From, |
| bool CopyingBaseSubobject, bool Copying) { |
| // Maybe we should use a memcpy? |
| if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() && |
| T.isTriviallyCopyableType(S.Context)) |
| return buildMemcpyForAssignmentOp(S, Loc, T, To, From); |
| |
| StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From, |
| CopyingBaseSubobject, |
| Copying, 0)); |
| |
| // If we ended up picking a trivial assignment operator for an array of a |
| // non-trivially-copyable class type, just emit a memcpy. |
| if (!Result.isInvalid() && !Result.get()) |
| return buildMemcpyForAssignmentOp(S, Loc, T, To, From); |
| |
| return Result; |
| } |
| |
| CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { |
| // Note: The following rules are largely analoguous to the copy |
| // constructor rules. Note that virtual bases are not taken into account |
| // for determining the argument type of the operator. Note also that |
| // operators taking an object instead of a reference are allowed. |
| assert(ClassDecl->needsImplicitCopyAssignment()); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| QualType ArgType = Context.getTypeDeclType(ClassDecl); |
| QualType RetType = Context.getLValueReferenceType(ArgType); |
| bool Const = ClassDecl->implicitCopyAssignmentHasConstParam(); |
| if (Const) |
| ArgType = ArgType.withConst(); |
| ArgType = Context.getLValueReferenceType(ArgType); |
| |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, |
| CXXCopyAssignment, |
| Const); |
| |
| // An implicitly-declared copy assignment operator is an inline public |
| // member of its class. |
| DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| CXXMethodDecl *CopyAssignment = |
| CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), |
| /*TInfo=*/nullptr, /*StorageClass=*/SC_None, |
| /*isInline=*/true, Constexpr, SourceLocation()); |
| CopyAssignment->setAccess(AS_public); |
| CopyAssignment->setDefaulted(); |
| CopyAssignment->setImplicit(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment, |
| CopyAssignment, |
| /* ConstRHS */ Const, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this member. |
| FunctionProtoType::ExtProtoInfo EPI = |
| getImplicitMethodEPI(*this, CopyAssignment); |
| CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); |
| |
| // Add the parameter to the operator. |
| ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment, |
| ClassLoc, ClassLoc, |
| /*Id=*/nullptr, ArgType, |
| /*TInfo=*/nullptr, SC_None, |
| nullptr); |
| CopyAssignment->setParams(FromParam); |
| |
| CopyAssignment->setTrivial( |
| ClassDecl->needsOverloadResolutionForCopyAssignment() |
| ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment) |
| : ClassDecl->hasTrivialCopyAssignment()); |
| |
| // Note that we have added this copy-assignment operator. |
| ++ASTContext::NumImplicitCopyAssignmentOperatorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, CopyAssignment); |
| |
| if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment)) |
| SetDeclDeleted(CopyAssignment, ClassLoc); |
| |
| if (S) |
| PushOnScopeChains(CopyAssignment, S, false); |
| ClassDecl->addDecl(CopyAssignment); |
| |
| return CopyAssignment; |
| } |
| |
| /// Diagnose an implicit copy operation for a class which is odr-used, but |
| /// which is deprecated because the class has a user-declared copy constructor, |
| /// copy assignment operator, or destructor. |
| static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) { |
| assert(CopyOp->isImplicit()); |
| |
| CXXRecordDecl *RD = CopyOp->getParent(); |
| CXXMethodDecl *UserDeclaredOperation = nullptr; |
| |
| // In Microsoft mode, assignment operations don't affect constructors and |
| // vice versa. |
| if (RD->hasUserDeclaredDestructor()) { |
| UserDeclaredOperation = RD->getDestructor(); |
| } else if (!isa<CXXConstructorDecl>(CopyOp) && |
| RD->hasUserDeclaredCopyConstructor() && |
| !S.getLangOpts().MSVCCompat) { |
| // Find any user-declared copy constructor. |
| for (auto *I : RD->ctors()) { |
| if (I->isCopyConstructor()) { |
| UserDeclaredOperation = I; |
| break; |
| } |
| } |
| assert(UserDeclaredOperation); |
| } else if (isa<CXXConstructorDecl>(CopyOp) && |
| RD->hasUserDeclaredCopyAssignment() && |
| !S.getLangOpts().MSVCCompat) { |
| // Find any user-declared move assignment operator. |
| for (auto *I : RD->methods()) { |
| if (I->isCopyAssignmentOperator()) { |
| UserDeclaredOperation = I; |
| break; |
| } |
| } |
| assert(UserDeclaredOperation); |
| } |
| |
| if (UserDeclaredOperation) { |
| S.Diag(UserDeclaredOperation->getLocation(), |
| diag::warn_deprecated_copy_operation) |
| << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp) |
| << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation); |
| } |
| } |
| |
| void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, |
| CXXMethodDecl *CopyAssignOperator) { |
| assert((CopyAssignOperator->isDefaulted() && |
| CopyAssignOperator->isOverloadedOperator() && |
| CopyAssignOperator->getOverloadedOperator() == OO_Equal && |
| !CopyAssignOperator->doesThisDeclarationHaveABody() && |
| !CopyAssignOperator->isDeleted()) && |
| "DefineImplicitCopyAssignment called for wrong function"); |
| if (CopyAssignOperator->willHaveBody() || CopyAssignOperator->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent(); |
| if (ClassDecl->isInvalidDecl()) { |
| CopyAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| SynthesizedFunctionScope Scope(*this, CopyAssignOperator); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| CopyAssignOperator->getType()->castAs<FunctionProtoType>()); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| // C++11 [class.copy]p18: |
| // The [definition of an implicitly declared copy assignment operator] is |
| // deprecated if the class has a user-declared copy constructor or a |
| // user-declared destructor. |
| if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit()) |
| diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator); |
| |
| // C++0x [class.copy]p30: |
| // The implicitly-defined or explicitly-defaulted copy assignment operator |
| // for a non-union class X performs memberwise copy assignment of its |
| // subobjects. The direct base classes of X are assigned first, in the |
| // order of their declaration in the base-specifier-list, and then the |
| // immediate non-static data members of X are assigned, in the order in |
| // which they were declared in the class definition. |
| |
| // The statements that form the synthesized function body. |
| SmallVector<Stmt*, 8> Statements; |
| |
| // The parameter for the "other" object, which we are copying from. |
| ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0); |
| Qualifiers OtherQuals = Other->getType().getQualifiers(); |
| QualType OtherRefType = Other->getType(); |
| if (const LValueReferenceType *OtherRef |
| = OtherRefType->getAs<LValueReferenceType>()) { |
| OtherRefType = OtherRef->getPointeeType(); |
| OtherQuals = OtherRefType.getQualifiers(); |
| } |
| |
| // Our location for everything implicitly-generated. |
| SourceLocation Loc = CopyAssignOperator->getLocEnd().isValid() |
| ? CopyAssignOperator->getLocEnd() |
| : CopyAssignOperator->getLocation(); |
| |
| // Builds a DeclRefExpr for the "other" object. |
| RefBuilder OtherRef(Other, OtherRefType); |
| |
| // Builds the "this" pointer. |
| ThisBuilder This; |
| |
| // Assign base classes. |
| bool Invalid = false; |
| for (auto &Base : ClassDecl->bases()) { |
| // Form the assignment: |
| // static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other)); |
| QualType BaseType = Base.getType().getUnqualifiedType(); |
| if (!BaseType->isRecordType()) { |
| Invalid = true; |
| continue; |
| } |
| |
| CXXCastPath BasePath; |
| BasePath.push_back(&Base); |
| |
| // Construct the "from" expression, which is an implicit cast to the |
| // appropriately-qualified base type. |
| CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals), |
| VK_LValue, BasePath); |
| |
| // Dereference "this". |
| DerefBuilder DerefThis(This); |
| CastBuilder To(DerefThis, |
| Context.getCVRQualifiedType( |
| BaseType, CopyAssignOperator->getTypeQualifiers()), |
| VK_LValue, BasePath); |
| |
| // Build the copy. |
| StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType, |
| To, From, |
| /*CopyingBaseSubobject=*/true, |
| /*Copying=*/true); |
| if (Copy.isInvalid()) { |
| CopyAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| // Success! Record the copy. |
| Statements.push_back(Copy.getAs<Expr>()); |
| } |
| |
| // Assign non-static members. |
| for (auto *Field : ClassDecl->fields()) { |
| // FIXME: We should form some kind of AST representation for the implied |
| // memcpy in a union copy operation. |
| if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) |
| continue; |
| |
| if (Field->isInvalidDecl()) { |
| Invalid = true; |
| continue; |
| } |
| |
| // Check for members of reference type; we can't copy those. |
| if (Field->getType()->isReferenceType()) { |
| Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) |
| << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); |
| Diag(Field->getLocation(), diag::note_declared_at); |
| Invalid = true; |
| continue; |
| } |
| |
| // Check for members of const-qualified, non-class type. |
| QualType BaseType = Context.getBaseElementType(Field->getType()); |
| if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) { |
| Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) |
| << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); |
| Diag(Field->getLocation(), diag::note_declared_at); |
| Invalid = true; |
| continue; |
| } |
| |
| // Suppress assigning zero-width bitfields. |
| if (Field->isZeroLengthBitField(Context)) |
| continue; |
| |
| QualType FieldType = Field->getType().getNonReferenceType(); |
| if (FieldType->isIncompleteArrayType()) { |
| assert(ClassDecl->hasFlexibleArrayMember() && |
| "Incomplete array type is not valid"); |
| continue; |
| } |
| |
| // Build references to the field in the object we're copying from and to. |
| CXXScopeSpec SS; // Intentionally empty |
| LookupResult MemberLookup(*this, Field->getDeclName(), Loc, |
| LookupMemberName); |
| MemberLookup.addDecl(Field); |
| MemberLookup.resolveKind(); |
| |
| MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup); |
| |
| MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup); |
| |
| // Build the copy of this field. |
| StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType, |
| To, From, |
| /*CopyingBaseSubobject=*/false, |
| /*Copying=*/true); |
| if (Copy.isInvalid()) { |
| CopyAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| // Success! Record the copy. |
| Statements.push_back(Copy.getAs<Stmt>()); |
| } |
| |
| if (!Invalid) { |
| // Add a "return *this;" |
| ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); |
| |
| StmtResult Return = BuildReturnStmt(Loc, ThisObj.get()); |
| if (Return.isInvalid()) |
| Invalid = true; |
| else |
| Statements.push_back(Return.getAs<Stmt>()); |
| } |
| |
| if (Invalid) { |
| CopyAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| StmtResult Body; |
| { |
| CompoundScopeRAII CompoundScope(*this); |
| Body = ActOnCompoundStmt(Loc, Loc, Statements, |
| /*isStmtExpr=*/false); |
| assert(!Body.isInvalid() && "Compound statement creation cannot fail"); |
| } |
| CopyAssignOperator->setBody(Body.getAs<Stmt>()); |
| CopyAssignOperator->markUsed(Context); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(CopyAssignOperator); |
| } |
| } |
| |
| CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { |
| assert(ClassDecl->needsImplicitMoveAssignment()); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| // Note: The following rules are largely analoguous to the move |
| // constructor rules. |
| |
| QualType ArgType = Context.getTypeDeclType(ClassDecl); |
| QualType RetType = Context.getLValueReferenceType(ArgType); |
| ArgType = Context.getRValueReferenceType(ArgType); |
| |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, |
| CXXMoveAssignment, |
| false); |
| |
| // An implicitly-declared move assignment operator is an inline public |
| // member of its class. |
| DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| CXXMethodDecl *MoveAssignment = |
| CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), |
| /*TInfo=*/nullptr, /*StorageClass=*/SC_None, |
| /*isInline=*/true, Constexpr, SourceLocation()); |
| MoveAssignment->setAccess(AS_public); |
| MoveAssignment->setDefaulted(); |
| MoveAssignment->setImplicit(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment, |
| MoveAssignment, |
| /* ConstRHS */ false, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this member. |
| FunctionProtoType::ExtProtoInfo EPI = |
| getImplicitMethodEPI(*this, MoveAssignment); |
| MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI)); |
| |
| // Add the parameter to the operator. |
| ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment, |
| ClassLoc, ClassLoc, |
| /*Id=*/nullptr, ArgType, |
| /*TInfo=*/nullptr, SC_None, |
| nullptr); |
| MoveAssignment->setParams(FromParam); |
| |
| MoveAssignment->setTrivial( |
| ClassDecl->needsOverloadResolutionForMoveAssignment() |
| ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment) |
| : ClassDecl->hasTrivialMoveAssignment()); |
| |
| // Note that we have added this copy-assignment operator. |
| ++ASTContext::NumImplicitMoveAssignmentOperatorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, MoveAssignment); |
| |
| if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) { |
| ClassDecl->setImplicitMoveAssignmentIsDeleted(); |
| SetDeclDeleted(MoveAssignment, ClassLoc); |
| } |
| |
| if (S) |
| PushOnScopeChains(MoveAssignment, S, false); |
| ClassDecl->addDecl(MoveAssignment); |
| |
| return MoveAssignment; |
| } |
| |
| /// Check if we're implicitly defining a move assignment operator for a class |
| /// with virtual bases. Such a move assignment might move-assign the virtual |
| /// base multiple times. |
| static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class, |
| SourceLocation CurrentLocation) { |
| assert(!Class->isDependentContext() && "should not define dependent move"); |
| |
| // Only a virtual base could get implicitly move-assigned multiple times. |
| // Only a non-trivial move assignment can observe this. We only want to |
| // diagnose if we implicitly define an assignment operator that assigns |
| // two base classes, both of which move-assign the same virtual base. |
| if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() || |
| Class->getNumBases() < 2) |
| return; |
| |
| llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist; |
| typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap; |
| VBaseMap VBases; |
| |
| for (auto &BI : Class->bases()) { |
| Worklist.push_back(&BI); |
| while (!Worklist.empty()) { |
| CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val(); |
| CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl(); |
| |
| // If the base has no non-trivial move assignment operators, |
| // we don't care about moves from it. |
| if (!Base->hasNonTrivialMoveAssignment()) |
| continue; |
| |
| // If there's nothing virtual here, skip it. |
| if (!BaseSpec->isVirtual() && !Base->getNumVBases()) |
| continue; |
| |
| // If we're not actually going to call a move assignment for this base, |
| // or the selected move assignment is trivial, skip it. |
| Sema::SpecialMemberOverloadResult SMOR = |
| S.LookupSpecialMember(Base, Sema::CXXMoveAssignment, |
| /*ConstArg*/false, /*VolatileArg*/false, |
| /*RValueThis*/true, /*ConstThis*/false, |
| /*VolatileThis*/false); |
| if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() || |
| !SMOR.getMethod()->isMoveAssignmentOperator()) |
| continue; |
| |
| if (BaseSpec->isVirtual()) { |
| // We're going to move-assign this virtual base, and its move |
| // assignment operator is not trivial. If this can happen for |
| // multiple distinct direct bases of Class, diagnose it. (If it |
| // only happens in one base, we'll diagnose it when synthesizing |
| // that base class's move assignment operator.) |
| CXXBaseSpecifier *&Existing = |
| VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI)) |
| .first->second; |
| if (Existing && Existing != &BI) { |
| S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times) |
| << Class << Base; |
| S.Diag(Existing->getLocStart(), diag::note_vbase_moved_here) |
| << (Base->getCanonicalDecl() == |
| Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl()) |
| << Base << Existing->getType() << Existing->getSourceRange(); |
| S.Diag(BI.getLocStart(), diag::note_vbase_moved_here) |
| << (Base->getCanonicalDecl() == |
| BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl()) |
| << Base << BI.getType() << BaseSpec->getSourceRange(); |
| |
| // Only diagnose each vbase once. |
| Existing = nullptr; |
| } |
| } else { |
| // Only walk over bases that have defaulted move assignment operators. |
| // We assume that any user-provided move assignment operator handles |
| // the multiple-moves-of-vbase case itself somehow. |
| if (!SMOR.getMethod()->isDefaulted()) |
| continue; |
| |
| // We're going to move the base classes of Base. Add them to the list. |
| for (auto &BI : Base->bases()) |
| Worklist.push_back(&BI); |
| } |
| } |
| } |
| } |
| |
| void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, |
| CXXMethodDecl *MoveAssignOperator) { |
| assert((MoveAssignOperator->isDefaulted() && |
| MoveAssignOperator->isOverloadedOperator() && |
| MoveAssignOperator->getOverloadedOperator() == OO_Equal && |
| !MoveAssignOperator->doesThisDeclarationHaveABody() && |
| !MoveAssignOperator->isDeleted()) && |
| "DefineImplicitMoveAssignment called for wrong function"); |
| if (MoveAssignOperator->willHaveBody() || MoveAssignOperator->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent(); |
| if (ClassDecl->isInvalidDecl()) { |
| MoveAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| // C++0x [class.copy]p28: |
| // The implicitly-defined or move assignment operator for a non-union class |
| // X performs memberwise move assignment of its subobjects. The direct base |
| // classes of X are assigned first, in the order of their declaration in the |
| // base-specifier-list, and then the immediate non-static data members of X |
| // are assigned, in the order in which they were declared in the class |
| // definition. |
| |
| // Issue a warning if our implicit move assignment operator will move |
| // from a virtual base more than once. |
| checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation); |
| |
| SynthesizedFunctionScope Scope(*this, MoveAssignOperator); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| MoveAssignOperator->getType()->castAs<FunctionProtoType>()); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| // The statements that form the synthesized function body. |
| SmallVector<Stmt*, 8> Statements; |
| |
| // The parameter for the "other" object, which we are move from. |
| ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0); |
| QualType OtherRefType = Other->getType()-> |
| getAs<RValueReferenceType>()->getPointeeType(); |
| assert(!OtherRefType.getQualifiers() && |
| "Bad argument type of defaulted move assignment"); |
| |
| // Our location for everything implicitly-generated. |
| SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid() |
| ? MoveAssignOperator->getLocEnd() |
| : MoveAssignOperator->getLocation(); |
| |
| // Builds a reference to the "other" object. |
| RefBuilder OtherRef(Other, OtherRefType); |
| // Cast to rvalue. |
| MoveCastBuilder MoveOther(OtherRef); |
| |
| // Builds the "this" pointer. |
| ThisBuilder This; |
| |
| // Assign base classes. |
| bool Invalid = false; |
| for (auto &Base : ClassDecl->bases()) { |
| // C++11 [class.copy]p28: |
| // It is unspecified whether subobjects representing virtual base classes |
| // are assigned more than once by the implicitly-defined copy assignment |
| // operator. |
| // FIXME: Do not assign to a vbase that will be assigned by some other base |
| // class. For a move-assignment, this can result in the vbase being moved |
| // multiple times. |
| |
| // Form the assignment: |
| // static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other)); |
| QualType BaseType = Base.getType().getUnqualifiedType(); |
| if (!BaseType->isRecordType()) { |
| Invalid = true; |
| continue; |
| } |
| |
| CXXCastPath BasePath; |
| BasePath.push_back(&Base); |
| |
| // Construct the "from" expression, which is an implicit cast to the |
| // appropriately-qualified base type. |
| CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath); |
| |
| // Dereference "this". |
| DerefBuilder DerefThis(This); |
| |
| // Implicitly cast "this" to the appropriately-qualified base type. |
| CastBuilder To(DerefThis, |
| Context.getCVRQualifiedType( |
| BaseType, MoveAssignOperator->getTypeQualifiers()), |
| VK_LValue, BasePath); |
| |
| // Build the move. |
| StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType, |
| To, From, |
| /*CopyingBaseSubobject=*/true, |
| /*Copying=*/false); |
| if (Move.isInvalid()) { |
| MoveAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| // Success! Record the move. |
| Statements.push_back(Move.getAs<Expr>()); |
| } |
| |
| // Assign non-static members. |
| for (auto *Field : ClassDecl->fields()) { |
| // FIXME: We should form some kind of AST representation for the implied |
| // memcpy in a union copy operation. |
| if (Field->isUnnamedBitfield() || Field->getParent()->isUnion()) |
| continue; |
| |
| if (Field->isInvalidDecl()) { |
| Invalid = true; |
| continue; |
| } |
| |
| // Check for members of reference type; we can't move those. |
| if (Field->getType()->isReferenceType()) { |
| Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) |
| << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName(); |
| Diag(Field->getLocation(), diag::note_declared_at); |
| Invalid = true; |
| continue; |
| } |
| |
| // Check for members of const-qualified, non-class type. |
| QualType BaseType = Context.getBaseElementType(Field->getType()); |
| if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) { |
| Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign) |
| << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName(); |
| Diag(Field->getLocation(), diag::note_declared_at); |
| Invalid = true; |
| continue; |
| } |
| |
| // Suppress assigning zero-width bitfields. |
| if (Field->isZeroLengthBitField(Context)) |
| continue; |
| |
| QualType FieldType = Field->getType().getNonReferenceType(); |
| if (FieldType->isIncompleteArrayType()) { |
| assert(ClassDecl->hasFlexibleArrayMember() && |
| "Incomplete array type is not valid"); |
| continue; |
| } |
| |
| // Build references to the field in the object we're copying from and to. |
| LookupResult MemberLookup(*this, Field->getDeclName(), Loc, |
| LookupMemberName); |
| MemberLookup.addDecl(Field); |
| MemberLookup.resolveKind(); |
| MemberBuilder From(MoveOther, OtherRefType, |
| /*IsArrow=*/false, MemberLookup); |
| MemberBuilder To(This, getCurrentThisType(), |
| /*IsArrow=*/true, MemberLookup); |
| |
| assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue |
| "Member reference with rvalue base must be rvalue except for reference " |
| "members, which aren't allowed for move assignment."); |
| |
| // Build the move of this field. |
| StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType, |
| To, From, |
| /*CopyingBaseSubobject=*/false, |
| /*Copying=*/false); |
| if (Move.isInvalid()) { |
| MoveAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| // Success! Record the copy. |
| Statements.push_back(Move.getAs<Stmt>()); |
| } |
| |
| if (!Invalid) { |
| // Add a "return *this;" |
| ExprResult ThisObj = |
| CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc)); |
| |
| StmtResult Return = BuildReturnStmt(Loc, ThisObj.get()); |
| if (Return.isInvalid()) |
| Invalid = true; |
| else |
| Statements.push_back(Return.getAs<Stmt>()); |
| } |
| |
| if (Invalid) { |
| MoveAssignOperator->setInvalidDecl(); |
| return; |
| } |
| |
| StmtResult Body; |
| { |
| CompoundScopeRAII CompoundScope(*this); |
| Body = ActOnCompoundStmt(Loc, Loc, Statements, |
| /*isStmtExpr=*/false); |
| assert(!Body.isInvalid() && "Compound statement creation cannot fail"); |
| } |
| MoveAssignOperator->setBody(Body.getAs<Stmt>()); |
| MoveAssignOperator->markUsed(Context); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(MoveAssignOperator); |
| } |
| } |
| |
| CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( |
| CXXRecordDecl *ClassDecl) { |
| // C++ [class.copy]p4: |
| // If the class definition does not explicitly declare a copy |
| // constructor, one is declared implicitly. |
| assert(ClassDecl->needsImplicitCopyConstructor()); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| QualType ClassType = Context.getTypeDeclType(ClassDecl); |
| QualType ArgType = ClassType; |
| bool Const = ClassDecl->implicitCopyConstructorHasConstParam(); |
| if (Const) |
| ArgType = ArgType.withConst(); |
| ArgType = Context.getLValueReferenceType(ArgType); |
| |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, |
| CXXCopyConstructor, |
| Const); |
| |
| DeclarationName Name |
| = Context.DeclarationNames.getCXXConstructorName( |
| Context.getCanonicalType(ClassType)); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| |
| // An implicitly-declared copy constructor is an inline public |
| // member of its class. |
| CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create( |
| Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, |
| /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, |
| Constexpr); |
| CopyConstructor->setAccess(AS_public); |
| CopyConstructor->setDefaulted(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor, |
| CopyConstructor, |
| /* ConstRHS */ Const, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this member. |
| FunctionProtoType::ExtProtoInfo EPI = |
| getImplicitMethodEPI(*this, CopyConstructor); |
| CopyConstructor->setType( |
| Context.getFunctionType(Context.VoidTy, ArgType, EPI)); |
| |
| // Add the parameter to the constructor. |
| ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor, |
| ClassLoc, ClassLoc, |
| /*IdentifierInfo=*/nullptr, |
| ArgType, /*TInfo=*/nullptr, |
| SC_None, nullptr); |
| CopyConstructor->setParams(FromParam); |
| |
| CopyConstructor->setTrivial( |
| ClassDecl->needsOverloadResolutionForCopyConstructor() |
| ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor) |
| : ClassDecl->hasTrivialCopyConstructor()); |
| |
| CopyConstructor->setTrivialForCall( |
| ClassDecl->hasAttr<TrivialABIAttr>() || |
| (ClassDecl->needsOverloadResolutionForCopyConstructor() |
| ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor, |
| TAH_ConsiderTrivialABI) |
| : ClassDecl->hasTrivialCopyConstructorForCall())); |
| |
| // Note that we have declared this constructor. |
| ++ASTContext::NumImplicitCopyConstructorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, CopyConstructor); |
| |
| if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) { |
| ClassDecl->setImplicitCopyConstructorIsDeleted(); |
| SetDeclDeleted(CopyConstructor, ClassLoc); |
| } |
| |
| if (S) |
| PushOnScopeChains(CopyConstructor, S, false); |
| ClassDecl->addDecl(CopyConstructor); |
| |
| return CopyConstructor; |
| } |
| |
| void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, |
| CXXConstructorDecl *CopyConstructor) { |
| assert((CopyConstructor->isDefaulted() && |
| CopyConstructor->isCopyConstructor() && |
| !CopyConstructor->doesThisDeclarationHaveABody() && |
| !CopyConstructor->isDeleted()) && |
| "DefineImplicitCopyConstructor - call it for implicit copy ctor"); |
| if (CopyConstructor->willHaveBody() || CopyConstructor->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = CopyConstructor->getParent(); |
| assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); |
| |
| SynthesizedFunctionScope Scope(*this, CopyConstructor); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| CopyConstructor->getType()->castAs<FunctionProtoType>()); |
| MarkVTableUsed(CurrentLocation, ClassDecl); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| // C++11 [class.copy]p7: |
| // The [definition of an implicitly declared copy constructor] is |
| // deprecated if the class has a user-declared copy assignment operator |
| // or a user-declared destructor. |
| if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit()) |
| diagnoseDeprecatedCopyOperation(*this, CopyConstructor); |
| |
| if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) { |
| CopyConstructor->setInvalidDecl(); |
| } else { |
| SourceLocation Loc = CopyConstructor->getLocEnd().isValid() |
| ? CopyConstructor->getLocEnd() |
| : CopyConstructor->getLocation(); |
| Sema::CompoundScopeRAII CompoundScope(*this); |
| CopyConstructor->setBody( |
| ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>()); |
| CopyConstructor->markUsed(Context); |
| } |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(CopyConstructor); |
| } |
| } |
| |
| CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( |
| CXXRecordDecl *ClassDecl) { |
| assert(ClassDecl->needsImplicitMoveConstructor()); |
| |
| DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor); |
| if (DSM.isAlreadyBeingDeclared()) |
| return nullptr; |
| |
| QualType ClassType = Context.getTypeDeclType(ClassDecl); |
| QualType ArgType = Context.getRValueReferenceType(ClassType); |
| |
| bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl, |
| CXXMoveConstructor, |
| false); |
| |
| DeclarationName Name |
| = Context.DeclarationNames.getCXXConstructorName( |
| Context.getCanonicalType(ClassType)); |
| SourceLocation ClassLoc = ClassDecl->getLocation(); |
| DeclarationNameInfo NameInfo(Name, ClassLoc); |
| |
| // C++11 [class.copy]p11: |
| // An implicitly-declared copy/move constructor is an inline public |
| // member of its class. |
| CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create( |
| Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, |
| /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true, |
| Constexpr); |
| MoveConstructor->setAccess(AS_public); |
| MoveConstructor->setDefaulted(); |
| |
| if (getLangOpts().CUDA) { |
| inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor, |
| MoveConstructor, |
| /* ConstRHS */ false, |
| /* Diagnose */ false); |
| } |
| |
| // Build an exception specification pointing back at this member. |
| FunctionProtoType::ExtProtoInfo EPI = |
| getImplicitMethodEPI(*this, MoveConstructor); |
| MoveConstructor->setType( |
| Context.getFunctionType(Context.VoidTy, ArgType, EPI)); |
| |
| // Add the parameter to the constructor. |
| ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor, |
| ClassLoc, ClassLoc, |
| /*IdentifierInfo=*/nullptr, |
| ArgType, /*TInfo=*/nullptr, |
| SC_None, nullptr); |
| MoveConstructor->setParams(FromParam); |
| |
| MoveConstructor->setTrivial( |
| ClassDecl->needsOverloadResolutionForMoveConstructor() |
| ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor) |
| : ClassDecl->hasTrivialMoveConstructor()); |
| |
| MoveConstructor->setTrivialForCall( |
| ClassDecl->hasAttr<TrivialABIAttr>() || |
| (ClassDecl->needsOverloadResolutionForMoveConstructor() |
| ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor, |
| TAH_ConsiderTrivialABI) |
| : ClassDecl->hasTrivialMoveConstructorForCall())); |
| |
| // Note that we have declared this constructor. |
| ++ASTContext::NumImplicitMoveConstructorsDeclared; |
| |
| Scope *S = getScopeForContext(ClassDecl); |
| CheckImplicitSpecialMemberDeclaration(S, MoveConstructor); |
| |
| if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) { |
| ClassDecl->setImplicitMoveConstructorIsDeleted(); |
| SetDeclDeleted(MoveConstructor, ClassLoc); |
| } |
| |
| if (S) |
| PushOnScopeChains(MoveConstructor, S, false); |
| ClassDecl->addDecl(MoveConstructor); |
| |
| return MoveConstructor; |
| } |
| |
| void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, |
| CXXConstructorDecl *MoveConstructor) { |
| assert((MoveConstructor->isDefaulted() && |
| MoveConstructor->isMoveConstructor() && |
| !MoveConstructor->doesThisDeclarationHaveABody() && |
| !MoveConstructor->isDeleted()) && |
| "DefineImplicitMoveConstructor - call it for implicit move ctor"); |
| if (MoveConstructor->willHaveBody() || MoveConstructor->isInvalidDecl()) |
| return; |
| |
| CXXRecordDecl *ClassDecl = MoveConstructor->getParent(); |
| assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor"); |
| |
| SynthesizedFunctionScope Scope(*this, MoveConstructor); |
| |
| // The exception specification is needed because we are defining the |
| // function. |
| ResolveExceptionSpec(CurrentLocation, |
| MoveConstructor->getType()->castAs<FunctionProtoType>()); |
| MarkVTableUsed(CurrentLocation, ClassDecl); |
| |
| // Add a context note for diagnostics produced after this point. |
| Scope.addContextNote(CurrentLocation); |
| |
| if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) { |
| MoveConstructor->setInvalidDecl(); |
| } else { |
| SourceLocation Loc = MoveConstructor->getLocEnd().isValid() |
| ? MoveConstructor->getLocEnd() |
| : MoveConstructor->getLocation(); |
| Sema::CompoundScopeRAII CompoundScope(*this); |
| MoveConstructor->setBody(ActOnCompoundStmt( |
| Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>()); |
| MoveConstructor->markUsed(Context); |
| } |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(MoveConstructor); |
| } |
| } |
| |
| bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { |
| return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD); |
| } |
| |
| void Sema::DefineImplicitLambdaToFunctionPointerConversion( |
| SourceLocation CurrentLocation, |
| CXXConversionDecl *Conv) { |
| SynthesizedFunctionScope Scope(*this, Conv); |
| assert(!Conv->getReturnType()->isUndeducedType()); |
| |
| CXXRecordDecl *Lambda = Conv->getParent(); |
| FunctionDecl *CallOp = Lambda->getLambdaCallOperator(); |
| FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker(); |
| |
| if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) { |
| CallOp = InstantiateFunctionDeclaration( |
| CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); |
| if (!CallOp) |
| return; |
| |
| Invoker = InstantiateFunctionDeclaration( |
| Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation); |
| if (!Invoker) |
| return; |
| } |
| |
| if (CallOp->isInvalidDecl()) |
| return; |
| |
| // Mark the call operator referenced (and add to pending instantiations |
| // if necessary). |
| // For both the conversion and static-invoker template specializations |
| // we construct their body's in this function, so no need to add them |
| // to the PendingInstantiations. |
| MarkFunctionReferenced(CurrentLocation, CallOp); |
| |
| // Fill in the __invoke function with a dummy implementation. IR generation |
| // will fill in the actual details. Update its type in case it contained |
| // an 'auto'. |
| Invoker->markUsed(Context); |
| Invoker->setReferenced(); |
| Invoker->setType(Conv->getReturnType()->getPointeeType()); |
| Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation())); |
| |
| // Construct the body of the conversion function { return __invoke; }. |
| Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(), |
| VK_LValue, Conv->getLocation()).get(); |
| assert(FunctionRef && "Can't refer to __invoke function?"); |
| Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get(); |
| Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(), |
| Conv->getLocation())); |
| Conv->markUsed(Context); |
| Conv->setReferenced(); |
| |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(Conv); |
| L->CompletedImplicitDefinition(Invoker); |
| } |
| } |
| |
| |
| |
| void Sema::DefineImplicitLambdaToBlockPointerConversion( |
| SourceLocation CurrentLocation, |
| CXXConversionDecl *Conv) |
| { |
| assert(!Conv->getParent()->isGenericLambda()); |
| |
| SynthesizedFunctionScope Scope(*this, Conv); |
| |
| // Copy-initialize the lambda object as needed to capture it. |
| Expr *This = ActOnCXXThis(CurrentLocation).get(); |
| Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get(); |
| |
| ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation, |
| Conv->getLocation(), |
| Conv, DerefThis); |
| |
| // If we're not under ARC, make sure we still get the _Block_copy/autorelease |
| // behavior. Note that only the general conversion function does this |
| // (since it's unusable otherwise); in the case where we inline the |
| // block literal, it has block literal lifetime semantics. |
| if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount) |
| BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(), |
| CK_CopyAndAutoreleaseBlockObject, |
| BuildBlock.get(), nullptr, VK_RValue); |
| |
| if (BuildBlock.isInvalid()) { |
| Diag(CurrentLocation, diag::note_lambda_to_block_conv); |
| Conv->setInvalidDecl(); |
| return; |
| } |
| |
| // Create the return statement that returns the block from the conversion |
| // function. |
| StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get()); |
| if (Return.isInvalid()) { |
| Diag(CurrentLocation, diag::note_lambda_to_block_conv); |
| Conv->setInvalidDecl(); |
| return; |
| } |
| |
| // Set the body of the conversion function. |
| Stmt *ReturnS = Return.get(); |
| Conv->setBody(CompoundStmt::Create(Context, ReturnS, Conv->getLocation(), |
| Conv->getLocation())); |
| Conv->markUsed(Context); |
| |
| // We're done; notify the mutation listener, if any. |
| if (ASTMutationListener *L = getASTMutationListener()) { |
| L->CompletedImplicitDefinition(Conv); |
| } |
| } |
| |
| /// Determine whether the given list arguments contains exactly one |
| /// "real" (non-default) argument. |
| static bool hasOneRealArgument(MultiExprArg Args) { |
| switch (Args.size()) { |
| case 0: |
| return false; |
| |
| default: |
| if (!Args[1]->isDefaultArgument()) |
| return false; |
| |
| LLVM_FALLTHROUGH; |
| case 1: |
| return !Args[0]->isDefaultArgument(); |
| } |
| |
| return false; |
| } |
| |
| ExprResult |
| Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, |
| NamedDecl *FoundDecl, |
| CXXConstructorDecl *Constructor, |
| MultiExprArg ExprArgs, |
| bool HadMultipleCandidates, |
| bool IsListInitialization, |
| bool IsStdInitListInitialization, |
| bool RequiresZeroInit, |
| unsigned ConstructKind, |
| SourceRange ParenRange) { |
| bool Elidable = false; |
| |
| // C++0x [class.copy]p34: |
| // When certain criteria are met, an implementation is allowed to |
| // omit the copy/move construction of a class object, even if the |
| // copy/move constructor and/or destructor for the object have |
| // side effects. [...] |
| // - when a temporary class object that has not been bound to a |
| // reference (12.2) would be copied/moved to a class object |
| // with the same cv-unqualified type, the copy/move operation |
| // can be omitted by constructing the temporary object |
| // directly into the target of the omitted copy/move |
| if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor && |
| Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) { |
| Expr *SubExpr = ExprArgs[0]; |
| Elidable = SubExpr->isTemporaryObject( |
| Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext())); |
| } |
| |
| return BuildCXXConstructExpr(ConstructLoc, DeclInitType, |
| FoundDecl, Constructor, |
| Elidable, ExprArgs, HadMultipleCandidates, |
| IsListInitialization, |
| IsStdInitListInitialization, RequiresZeroInit, |
| ConstructKind, ParenRange); |
| } |
| |
| ExprResult |
| Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, |
| NamedDecl *FoundDecl, |
| CXXConstructorDecl *Constructor, |
| bool Elidable, |
| MultiExprArg ExprArgs, |
| bool HadMultipleCandidates, |
| bool IsListInitialization, |
| bool IsStdInitListInitialization, |
| bool RequiresZeroInit, |
| unsigned ConstructKind, |
| SourceRange ParenRange) { |
| if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) { |
| Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow); |
| if (DiagnoseUseOfDecl(Constructor, ConstructLoc)) |
| return ExprError(); |
| } |
| |
| return BuildCXXConstructExpr( |
| ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, |
| HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, |
| RequiresZeroInit, ConstructKind, ParenRange); |
| } |
| |
| /// BuildCXXConstructExpr - Creates a complete call to a constructor, |
| /// including handling of its default argument expressions. |
| ExprResult |
| Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, |
| CXXConstructorDecl *Constructor, |
| bool Elidable, |
| MultiExprArg ExprArgs, |
| bool HadMultipleCandidates, |
| bool IsListInitialization, |
| bool IsStdInitListInitialization, |
| bool RequiresZeroInit, |
| unsigned ConstructKind, |
| SourceRange ParenRange) { |
| assert(declaresSameEntity( |
| Constructor->getParent(), |
| DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) && |
| "given constructor for wrong type"); |
| MarkFunctionReferenced(ConstructLoc, Constructor); |
| if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor)) |
| return ExprError(); |
| |
| return CXXConstructExpr::Create( |
| Context, DeclInitType, ConstructLoc, Constructor, Elidable, |
| ExprArgs, HadMultipleCandidates, IsListInitialization, |
| IsStdInitListInitialization, RequiresZeroInit, |
| static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), |
| ParenRange); |
| } |
| |
| ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { |
| assert(Field->hasInClassInitializer()); |
| |
| // If we already have the in-class initializer nothing needs to be done. |
| if (Field->getInClassInitializer()) |
| return CXXDefaultInitExpr::Create(Context, Loc, Field); |
| |
| // If we might have already tried and failed to instantiate, don't try again. |
| if (Field->isInvalidDecl()) |
| return ExprError(); |
| |
| // Maybe we haven't instantiated the in-class initializer. Go check the |
| // pattern FieldDecl to see if it has one. |
| CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent()); |
| |
| if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) { |
| CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern(); |
| DeclContext::lookup_result Lookup = |
| ClassPattern->lookup(Field->getDeclName()); |
| |
| // Lookup can return at most two results: the pattern for the field, or the |
| // injected class name of the parent record. No other member can have the |
| // same name as the field. |
| // In modules mode, lookup can return multiple results (coming from |
| // different modules). |
| assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) && |
| "more than two lookup results for field name"); |
| FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]); |
| if (!Pattern) { |
| assert(isa<CXXRecordDecl>(Lookup[0]) && |
| "cannot have other non-field member with same name"); |
| for (auto L : Lookup) |
| if (isa<FieldDecl>(L)) { |
| Pattern = cast<FieldDecl>(L); |
| break; |
| } |
| assert(Pattern && "We must have set the Pattern!"); |
| } |
| |
| if (!Pattern->hasInClassInitializer() || |
| InstantiateInClassInitializer(Loc, Field, Pattern, |
| getTemplateInstantiationArgs(Field))) { |
| // Don't diagnose this again. |
| Field->setInvalidDecl(); |
| return ExprError(); |
| } |
| return CXXDefaultInitExpr::Create(Context, Loc, Field); |
| } |
| |
| // DR1351: |
| // If the brace-or-equal-initializer of a non-static data member |
| // invokes a defaulted default constructor of its class or of an |
| // enclosing class in a potentially evaluated subexpression, the |
| // program is ill-formed. |
| // |
| // This resolution is unworkable: the exception specification of the |
| // default constructor can be needed in an unevaluated context, in |
| // particular, in the operand of a noexcept-expression, and we can be |
| // unable to compute an exception specification for an enclosed class. |
| // |
| // Any attempt to resolve the exception specification of a defaulted default |
| // constructor before the initializer is lexically complete will ultimately |
| // come here at which point we can diagnose it. |
| RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext(); |
| Diag(Loc, diag::err_in_class_initializer_not_yet_parsed) |
| << OutermostClass << Field; |
| Diag(Field->getLocEnd(), diag::note_in_class_initializer_not_yet_parsed); |
| // Recover by marking the field invalid, unless we're in a SFINAE context. |
| if (!isSFINAEContext()) |
| Field->setInvalidDecl(); |
| return ExprError(); |
| } |
| |
| void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) { |
| if (VD->isInvalidDecl()) return; |
| |
| CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl()); |
| if (ClassDecl->isInvalidDecl()) return; |
| if (ClassDecl->hasIrrelevantDestructor()) return; |
| if (ClassDecl->isDependentContext()) return; |
| |
| CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl); |
| MarkFunctionReferenced(VD->getLocation(), Destructor); |
| CheckDestructorAccess(VD->getLocation(), Destructor, |
| PDiag(diag::err_access_dtor_var) |
| << VD->getDeclName() |
| << VD->getType()); |
| DiagnoseUseOfDecl(Destructor, VD->getLocation()); |
| |
| if (Destructor->isTrivial()) return; |
| if (!VD->hasGlobalStorage()) return; |
| |
| // Emit warning for non-trivial dtor in global scope (a real global, |
| // class-static, function-static). |
| Diag(VD->getLocation(), diag::warn_exit_time_destructor); |
| |
| // TODO: this should be re-enabled for static locals by !CXAAtExit |
| if (!VD->isStaticLocal()) |
| Diag(VD->getLocation(), diag::warn_global_destructor); |
| } |
| |
| /// Given a constructor and the set of arguments provided for the |
| /// constructor, convert the arguments and add any required default arguments |
| /// to form a proper call to this constructor. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool |
| Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor, |
| MultiExprArg ArgsPtr, |
| SourceLocation Loc, |
| SmallVectorImpl<Expr*> &ConvertedArgs, |
| bool AllowExplicit, |
| bool IsListInitialization) { |
| // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall. |
| unsigned NumArgs = ArgsPtr.size(); |
| Expr **Args = ArgsPtr.data(); |
| |
| const FunctionProtoType *Proto |
| = Constructor->getType()->getAs<FunctionProtoType>(); |
| assert(Proto && "Constructor without a prototype?"); |
| unsigned NumParams = Proto->getNumParams(); |
| |
| // If too few arguments are available, we'll fill in the rest with defaults. |
| if (NumArgs < NumParams) |
| ConvertedArgs.reserve(NumParams); |
| else |
| ConvertedArgs.reserve(NumArgs); |
| |
| VariadicCallType CallType = |
| Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply; |
| SmallVector<Expr *, 8> AllArgs; |
| bool Invalid = GatherArgumentsForCall(Loc, Constructor, |
| Proto, 0, |
| llvm::makeArrayRef(Args, NumArgs), |
| AllArgs, |
| CallType, AllowExplicit, |
| IsListInitialization); |
| ConvertedArgs.append(AllArgs.begin(), AllArgs.end()); |
| |
| DiagnoseSentinelCalls(Constructor, Loc, AllArgs); |
| |
| CheckConstructorCall(Constructor, |
| llvm::makeArrayRef(AllArgs.data(), AllArgs.size()), |
| Proto, Loc); |
| |
| return Invalid; |
| } |
| |
| static inline bool |
| CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, |
| const FunctionDecl *FnDecl) { |
| const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext(); |
| if (isa<NamespaceDecl>(DC)) { |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_declared_in_namespace) |
| << FnDecl->getDeclName(); |
| } |
| |
| if (isa<TranslationUnitDecl>(DC) && |
| FnDecl->getStorageClass() == SC_Static) { |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_declared_static) |
| << FnDecl->getDeclName(); |
| } |
| |
| return false; |
| } |
| |
| static QualType |
| RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) { |
| QualType QTy = PtrTy->getPointeeType(); |
| QTy = SemaRef.Context.removeAddrSpaceQualType(QTy); |
| return SemaRef.Context.getPointerType(QTy); |
| } |
| |
| static inline bool |
| CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl, |
| CanQualType ExpectedResultType, |
| CanQualType ExpectedFirstParamType, |
| unsigned DependentParamTypeDiag, |
| unsigned InvalidParamTypeDiag) { |
| QualType ResultType = |
| FnDecl->getType()->getAs<FunctionType>()->getReturnType(); |
| |
| // Check that the result type is not dependent. |
| if (ResultType->isDependentType()) |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_dependent_result_type) |
| << FnDecl->getDeclName() << ExpectedResultType; |
| |
| // OpenCL C++: the operator is valid on any address space. |
| if (SemaRef.getLangOpts().OpenCLCPlusPlus) { |
| if (auto *PtrTy = ResultType->getAs<PointerType>()) { |
| ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); |
| } |
| } |
| |
| // Check that the result type is what we expect. |
| if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType) |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_invalid_result_type) |
| << FnDecl->getDeclName() << ExpectedResultType; |
| |
| // A function template must have at least 2 parameters. |
| if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2) |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_template_too_few_parameters) |
| << FnDecl->getDeclName(); |
| |
| // The function decl must have at least 1 parameter. |
| if (FnDecl->getNumParams() == 0) |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_delete_too_few_parameters) |
| << FnDecl->getDeclName(); |
| |
| // Check the first parameter type is not dependent. |
| QualType FirstParamType = FnDecl->getParamDecl(0)->getType(); |
| if (FirstParamType->isDependentType()) |
| return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag) |
| << FnDecl->getDeclName() << ExpectedFirstParamType; |
| |
| // Check that the first parameter type is what we expect. |
| if (SemaRef.getLangOpts().OpenCLCPlusPlus) { |
| // OpenCL C++: the operator is valid on any address space. |
| if (auto *PtrTy = |
| FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) { |
| FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy); |
| } |
| } |
| if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() != |
| ExpectedFirstParamType) |
| return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag) |
| << FnDecl->getDeclName() << ExpectedFirstParamType; |
| |
| return false; |
| } |
| |
| static bool |
| CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) { |
| // C++ [basic.stc.dynamic.allocation]p1: |
| // A program is ill-formed if an allocation function is declared in a |
| // namespace scope other than global scope or declared static in global |
| // scope. |
| if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) |
| return true; |
| |
| CanQualType SizeTy = |
| SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType()); |
| |
| // C++ [basic.stc.dynamic.allocation]p1: |
| // The return type shall be void*. The first parameter shall have type |
| // std::size_t. |
| if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy, |
| SizeTy, |
| diag::err_operator_new_dependent_param_type, |
| diag::err_operator_new_param_type)) |
| return true; |
| |
| // C++ [basic.stc.dynamic.allocation]p1: |
| // The first parameter shall not have an associated default argument. |
| if (FnDecl->getParamDecl(0)->hasDefaultArg()) |
| return SemaRef.Diag(FnDecl->getLocation(), |
| diag::err_operator_new_default_arg) |
| << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange(); |
| |
| return false; |
| } |
| |
| static bool |
| CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) { |
| // C++ [basic.stc.dynamic.deallocation]p1: |
| // A program is ill-formed if deallocation functions are declared in a |
| // namespace scope other than global scope or declared static in global |
| // scope. |
| if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl)) |
| return true; |
| |
| auto *MD = dyn_cast<CXXMethodDecl>(FnDecl); |
| |
| // C++ P0722: |
| // Within a class C, the first parameter of a destroying operator delete |
| // shall be of type C *. The first parameter of any other deallocation |
| // function shall be of type void *. |
| CanQualType ExpectedFirstParamType = |
| MD && MD->isDestroyingOperatorDelete() |
| ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType( |
| SemaRef.Context.getRecordType(MD->getParent()))) |
| : SemaRef.Context.VoidPtrTy; |
| |
| // C++ [basic.stc.dynamic.deallocation]p2: |
| // Each deallocation function shall return void |
| if (CheckOperatorNewDeleteTypes( |
| SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType, |
| diag::err_operator_delete_dependent_param_type, |
| diag::err_operator_delete_param_type)) |
| return true; |
| |
| // C++ P0722: |
| // A destroying operator delete shall be a usual deallocation function. |
| if (MD && !MD->getParent()->isDependentContext() && |
| MD->isDestroyingOperatorDelete() && !MD->isUsualDeallocationFunction()) { |
| SemaRef.Diag(MD->getLocation(), |
| diag::err_destroying_operator_delete_not_usual); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// CheckOverloadedOperatorDeclaration - Check whether the declaration |
| /// of this overloaded operator is well-formed. If so, returns false; |
| /// otherwise, emits appropriate diagnostics and returns true. |
| bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) { |
| assert(FnDecl && FnDecl->isOverloadedOperator() && |
| "Expected an overloaded operator declaration"); |
| |
| OverloadedOperatorKind Op = FnDecl->getOverloadedOperator(); |
| |
| // C++ [over.oper]p5: |
| // The allocation and deallocation functions, operator new, |
| // operator new[], operator delete and operator delete[], are |
| // described completely in 3.7.3. The attributes and restrictions |
| // found in the rest of this subclause do not apply to them unless |
| // explicitly stated in 3.7.3. |
| if (Op == OO_Delete || Op == OO_Array_Delete) |
| return CheckOperatorDeleteDeclaration(*this, FnDecl); |
| |
| if (Op == OO_New || Op == OO_Array_New) |
| return CheckOperatorNewDeclaration(*this, FnDecl); |
| |
| // C++ [over.oper]p6: |
| // An operator function shall either be a non-static member |
| // function or be a non-member function and have at least one |
| // parameter whose type is a class, a reference to a class, an |
| // enumeration, or a reference to an enumeration. |
| if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) { |
| if (MethodDecl->isStatic()) |
| return Diag(FnDecl->getLocation(), |
| diag::err_operator_overload_static) << FnDecl->getDeclName(); |
| } else { |
| bool ClassOrEnumParam = false; |
| for (auto Param : FnDecl->parameters()) { |
| QualType ParamType = Param->getType().getNonReferenceType(); |
| if (ParamType->isDependentType() || ParamType->isRecordType() || |
| ParamType->isEnumeralType()) { |
| ClassOrEnumParam = true; |
| break; |
| } |
| } |
| |
| if (!ClassOrEnumParam) |
| return Diag(FnDecl->getLocation(), |
| diag::err_operator_overload_needs_class_or_enum) |
| << FnDecl->getDeclName(); |
| } |
| |
| // C++ [over.oper]p8: |
| // An operator function cannot have default arguments (8.3.6), |
| // except where explicitly stated below. |
| // |
| // Only the function-call operator allows default arguments |
| // (C++ [over.call]p1). |
| if (Op != OO_Call) { |
| for (auto Param : FnDecl->parameters()) { |
| if (Param->hasDefaultArg()) |
| return Diag(Param->getLocation(), |
| diag::err_operator_overload_default_arg) |
| << FnDecl->getDeclName() << Param->getDefaultArgRange(); |
| } |
| } |
| |
| static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = { |
| { false, false, false } |
| #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ |
| , { Unary, Binary, MemberOnly } |
| #include "clang/Basic/OperatorKinds.def" |
| }; |
| |
| bool CanBeUnaryOperator = OperatorUses[Op][0]; |
| bool CanBeBinaryOperator = OperatorUses[Op][1]; |
| bool MustBeMemberOperator = OperatorUses[Op][2]; |
| |
| // C++ [over.oper]p8: |
| // [...] Operator functions cannot have more or fewer parameters |
| // than the number required for the corresponding operator, as |
| // described in the rest of this subclause. |
| unsigned NumParams = FnDecl->getNumParams() |
| + (isa<CXXMethodDecl>(FnDecl)? 1 : 0); |
| if (Op != OO_Call && |
| ((NumParams == 1 && !CanBeUnaryOperator) || |
| (NumParams == 2 && !CanBeBinaryOperator) || |
| (NumParams < 1) || (NumParams > 2))) { |
| // We have the wrong number of parameters. |
| unsigned ErrorKind; |
| if (CanBeUnaryOperator && CanBeBinaryOperator) { |
| ErrorKind = 2; // 2 -> unary or binary. |
| } else if (CanBeUnaryOperator) { |
| ErrorKind = 0; // 0 -> unary |
| } else { |
| assert(CanBeBinaryOperator && |
| "All non-call overloaded operators are unary or binary!"); |
| ErrorKind = 1; // 1 -> binary |
| } |
| |
| return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be) |
| << FnDecl->getDeclName() << NumParams << ErrorKind; |
| } |
| |
| // Overloaded operators other than operator() cannot be variadic. |
| if (Op != OO_Call && |
| FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) { |
| return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic) |
| << FnDecl->getDeclName(); |
| } |
| |
| // Some operators must be non-static member functions. |
| if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) { |
| return Diag(FnDecl->getLocation(), |
| diag::err_operator_overload_must_be_member) |
| << FnDecl->getDeclName(); |
| } |
| |
| // C++ [over.inc]p1: |
| // The user-defined function called operator++ implements the |
| // prefix and postfix ++ operator. If this function is a member |
| // function with no parameters, or a non-member function with one |
| // parameter of class or enumeration type, it defines the prefix |
| // increment operator ++ for objects of that type. If the function |
| // is a member function with one parameter (which shall be of type |
| // int) or a non-member function with two parameters (the second |
| // of which shall be of type int), it defines the postfix |
| // increment operator ++ for objects of that type. |
| if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) { |
| ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1); |
| QualType ParamType = LastParam->getType(); |
| |
| if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) && |
| !ParamType->isDependentType()) |
| return Diag(LastParam->getLocation(), |
| diag::err_operator_overload_post_incdec_must_be_int) |
| << LastParam->getType() << (Op == OO_MinusMinus); |
| } |
| |
| return false; |
| } |
| |
| static bool |
| checkLiteralOperatorTemplateParameterList(Sema &SemaRef, |
| FunctionTemplateDecl *TpDecl) { |
| TemplateParameterList *TemplateParams = TpDecl->getTemplateParameters(); |
| |
| // Must have one or two template parameters. |
| if (TemplateParams->size() == 1) { |
| NonTypeTemplateParmDecl *PmDecl = |
| dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(0)); |
| |
| // The template parameter must be a char parameter pack. |
| if (PmDecl && PmDecl->isTemplateParameterPack() && |
| SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy)) |
| return false; |
| |
| } else if (TemplateParams->size() == 2) { |
| TemplateTypeParmDecl *PmType = |
| dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0)); |
| NonTypeTemplateParmDecl *PmArgs = |
| dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(1)); |
| |
| // The second template parameter must be a parameter pack with the |
| // first template parameter as its type. |
| if (PmType && PmArgs && !PmType->isTemplateParameterPack() && |
| PmArgs->isTemplateParameterPack()) { |
| const TemplateTypeParmType *TArgs = |
| PmArgs->getType()->getAs<TemplateTypeParmType>(); |
| if (TArgs && TArgs->getDepth() == PmType->getDepth() && |
| TArgs->getIndex() == PmType->getIndex()) { |
| if (!SemaRef.inTemplateInstantiation()) |
| SemaRef.Diag(TpDecl->getLocation(), |
| diag::ext_string_literal_operator_template); |
| return false; |
| } |
| } |
| } |
| |
| SemaRef.Diag(TpDecl->getTemplateParameters()->getSourceRange().getBegin(), |
| diag::err_literal_operator_template) |
| << TpDecl->getTemplateParameters()->getSourceRange(); |
| return true; |
| } |
| |
| /// CheckLiteralOperatorDeclaration - Check whether the declaration |
| /// of this literal operator function is well-formed. If so, returns |
| /// false; otherwise, emits appropriate diagnostics and returns true. |
| bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) { |
| if (isa<CXXMethodDecl>(FnDecl)) { |
| Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace) |
| << FnDecl->getDeclName(); |
| return true; |
| } |
| |
| if (FnDecl->isExternC()) { |
| Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c); |
| if (const LinkageSpecDecl *LSD = |
| FnDecl->getDeclContext()->getExternCContext()) |
| Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here); |
| return true; |
| } |
| |
| // This might be the definition of a literal operator template. |
| FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate(); |
| |
| // This might be a specialization of a literal operator template. |
| if (!TpDecl) |
| TpDecl = FnDecl->getPrimaryTemplate(); |
| |
| // template <char...> type operator "" name() and |
| // template <class T, T...> type operator "" name() are the only valid |
| // template signatures, and the only valid signatures with no parameters. |
| if (TpDecl) { |
| if (FnDecl->param_size() != 0) { |
| Diag(FnDecl->getLocation(), |
| diag::err_literal_operator_template_with_params); |
| return true; |
| } |
| |
| if (checkLiteralOperatorTemplateParameterList(*this, TpDecl)) |
| return true; |
| |
| } else if (FnDecl->param_size() == 1) { |
| const ParmVarDecl *Param = FnDecl->getParamDecl(0); |
| |
| QualType ParamType = Param->getType().getUnqualifiedType(); |
| |
| // Only unsigned long long int, long double, any character type, and const |
| // char * are allowed as the only parameters. |
| if (ParamType->isSpecificBuiltinType(BuiltinType::ULongLong) || |
| ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) || |
| Context.hasSameType(ParamType, Context.CharTy) || |
| Context.hasSameType(ParamType, Context.WideCharTy) || |
| Context.hasSameType(ParamType, Context.Char8Ty) || |
| Context.hasSameType(ParamType, Context.Char16Ty) || |
| Context.hasSameType(ParamType, Context.Char32Ty)) { |
| } else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) { |
| QualType InnerType = Ptr->getPointeeType(); |
| |
| // Pointer parameter must be a const char *. |
| if (!(Context.hasSameType(InnerType.getUnqualifiedType(), |
| Context.CharTy) && |
| InnerType.isConstQualified() && !InnerType.isVolatileQualified())) { |
| Diag(Param->getSourceRange().getBegin(), |
| diag::err_literal_operator_param) |
| << ParamType << "'const char *'" << Param->getSourceRange(); |
| return true; |
| } |
| |
| } else if (ParamType->isRealFloatingType()) { |
| Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) |
| << ParamType << Context.LongDoubleTy << Param->getSourceRange(); |
| return true; |
| |
| } else if (ParamType->isIntegerType()) { |
| Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param) |
| << ParamType << Context.UnsignedLongLongTy << Param->getSourceRange(); |
| return true; |
| |
| } else { |
| Diag(Param->getSourceRange().getBegin(), |
| diag::err_literal_operator_invalid_param) |
| << ParamType << Param->getSourceRange(); |
| return true; |
| } |
| |
| } else if (FnDecl->param_size() == 2) { |
| FunctionDecl::param_iterator Param = FnDecl->param_begin(); |
| |
| // First, verify that the first parameter is correct. |
| |
| QualType FirstParamType = (*Param)->getType().getUnqualifiedType(); |
| |
| // Two parameter function must have a pointer to const as a |
| // first parameter; let's strip those qualifiers. |
| const PointerType *PT = FirstParamType->getAs<PointerType>(); |
| |
| if (!PT) { |
| Diag((*Param)->getSourceRange().getBegin(), |
| diag::err_literal_operator_param) |
| << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); |
| return true; |
| } |
| |
| QualType PointeeType = PT->getPointeeType(); |
| // First parameter must be const |
| if (!PointeeType.isConstQualified() || PointeeType.isVolatileQualified()) { |
| Diag((*Param)->getSourceRange().getBegin(), |
| diag::err_literal_operator_param) |
| << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); |
| return true; |
| } |
| |
| QualType InnerType = PointeeType.getUnqualifiedType(); |
| // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and |
| // const char32_t* are allowed as the first parameter to a two-parameter |
| // function |
| if (!(Context.hasSameType(InnerType, Context.CharTy) || |
| Context.hasSameType(InnerType, Context.WideCharTy) || |
| Context.hasSameType(InnerType, Context.Char8Ty) || |
| Context.hasSameType(InnerType, Context.Char16Ty) || |
| Context.hasSameType(InnerType, Context.Char32Ty))) { |
| Diag((*Param)->getSourceRange().getBegin(), |
| diag::err_literal_operator_param) |
| << FirstParamType << "'const char *'" << (*Param)->getSourceRange(); |
| return true; |
| } |
| |
| // Move on to the second and final parameter. |
| ++Param; |
| |
| // The second parameter must be a std::size_t. |
| QualType SecondParamType = (*Param)->getType().getUnqualifiedType(); |
| if (!Context.hasSameType(SecondParamType, Context.getSizeType())) { |
| Diag((*Param)->getSourceRange().getBegin(), |
| diag::err_literal_operator_param) |
| << SecondParamType << Context.getSizeType() |
| << (*Param)->getSourceRange(); |
| return true; |
| } |
| } else { |
| Diag(FnDecl->getLocation(), diag::err_literal_operator_bad_param_count); |
| return true; |
| } |
| |
| // Parameters are good. |
| |
| // A parameter-declaration-clause containing a default argument is not |
| // equivalent to any of the permitted forms. |
| for (auto Param : FnDecl->parameters()) { |
| if (Param->hasDefaultArg()) { |
| Diag(Param->getDefaultArgRange().getBegin(), |
| diag::err_literal_operator_default_argument) |
| << Param->getDefaultArgRange(); |
| break; |
| } |
| } |
| |
| StringRef LiteralName |
| = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName(); |
| if (LiteralName[0] != '_' && |
| !getSourceManager().isInSystemHeader(FnDecl->getLocation())) { |
| // C++11 [usrlit.suffix]p1: |
| // Literal suffix identifiers that do not start with an underscore |
| // are reserved for future standardization. |
| Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved) |
| << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName); |
| } |
| |
| return false; |
| } |
| |
| /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ |
| /// linkage specification, including the language and (if present) |
| /// the '{'. ExternLoc is the location of the 'extern', Lang is the |
| /// language string literal. LBraceLoc, if valid, provides the location of |
| /// the '{' brace. Otherwise, this linkage specification does not |
| /// have any braces. |
| Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc, |
| Expr *LangStr, |
| SourceLocation LBraceLoc) { |
| StringLiteral *Lit = cast<StringLiteral>(LangStr); |
| if (!Lit->isAscii()) { |
| Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii) |
| << LangStr->getSourceRange(); |
| return nullptr; |
| } |
| |
| StringRef Lang = Lit->getString(); |
| LinkageSpecDecl::LanguageIDs Language; |
| if (Lang == "C") |
| Language = LinkageSpecDecl::lang_c; |
| else if (Lang == "C++") |
| Language = LinkageSpecDecl::lang_cxx; |
| else { |
| Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown) |
| << LangStr->getSourceRange(); |
| return nullptr; |
| } |
| |
| // FIXME: Add all the various semantics of linkage specifications |
| |
| LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc, |
| LangStr->getExprLoc(), Language, |
| LBraceLoc.isValid()); |
| CurContext->addDecl(D); |
| PushDeclContext(S, D); |
| return D; |
| } |
| |
| /// ActOnFinishLinkageSpecification - Complete the definition of |
| /// the C++ linkage specification LinkageSpec. If RBraceLoc is |
| /// valid, it's the position of the closing '}' brace in a linkage |
| /// specification that uses braces. |
| Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, |
| Decl *LinkageSpec, |
| SourceLocation RBraceLoc) { |
| if (RBraceLoc.isValid()) { |
| LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec); |
| LSDecl->setRBraceLoc(RBraceLoc); |
| } |
| PopDeclContext(); |
| return LinkageSpec; |
| } |
| |
| Decl *Sema::ActOnEmptyDeclaration(Scope *S, |
| const ParsedAttributesView &AttrList, |
| SourceLocation SemiLoc) { |
| Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); |
| // Attribute declarations appertain to empty declaration so we handle |
| // them here. |
| ProcessDeclAttributeList(S, ED, AttrList); |
| |
| CurContext->addDecl(ED); |
| return ED; |
| } |
| |
| /// Perform semantic analysis for the variable declaration that |
| /// occurs within a C++ catch clause, returning the newly-created |
| /// variable. |
| VarDecl *Sema::BuildExceptionDeclaration(Scope *S, |
| TypeSourceInfo *TInfo, |
| SourceLocation StartLoc, |
| SourceLocation Loc, |
| IdentifierInfo *Name) { |
| bool Invalid = false; |
| QualType ExDeclType = TInfo->getType(); |
| |
| // Arrays and functions decay. |
| if (ExDeclType->isArrayType()) |
| ExDeclType = Context.getArrayDecayedType(ExDeclType); |
| else if (ExDeclType->isFunctionType()) |
| ExDeclType = Context.getPointerType(ExDeclType); |
| |
| // C++ 15.3p1: The exception-declaration shall not denote an incomplete type. |
| // The exception-declaration shall not denote a pointer or reference to an |
| // incomplete type, other than [cv] void*. |
| // N2844 forbids rvalue references. |
| if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) { |
| Diag(Loc, diag::err_catch_rvalue_ref); |
| Invalid = true; |
| } |
| |
| if (ExDeclType->isVariablyModifiedType()) { |
| Diag(Loc, diag::err_catch_variably_modified) << ExDeclType; |
| Invalid = true; |
| } |
| |
| QualType BaseType = ExDeclType; |
| int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference |
| unsigned DK = diag::err_catch_incomplete; |
| if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { |
| BaseType = Ptr->getPointeeType(); |
| Mode = 1; |
| DK = diag::err_catch_incomplete_ptr; |
| } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) { |
| // For the purpose of error recovery, we treat rvalue refs like lvalue refs. |
| BaseType = Ref->getPointeeType(); |
| Mode = 2; |
| DK = diag::err_catch_incomplete_ref; |
| } |
| if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) && |
| !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK)) |
| Invalid = true; |
| |
| if (!Invalid && !ExDeclType->isDependentType() && |
| RequireNonAbstractType(Loc, ExDeclType, |
| diag::err_abstract_type_in_decl, |
| AbstractVariableType)) |
| Invalid = true; |
| |
| // Only the non-fragile NeXT runtime currently supports C++ catches |
| // of ObjC types, and no runtime supports catching ObjC types by value. |
| if (!Invalid && getLangOpts().ObjC1) { |
| QualType T = ExDeclType; |
| if (const ReferenceType *RT = T->getAs<ReferenceType>()) |
| T = RT->getPointeeType(); |
| |
| if (T->isObjCObjectType()) { |
| Diag(Loc, diag::err_objc_object_catch); |
| Invalid = true; |
| } else if (T->isObjCObjectPointerType()) { |
| // FIXME: should this be a test for macosx-fragile specifically? |
| if (getLangOpts().ObjCRuntime.isFragile()) |
| Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile); |
| } |
| } |
| |
| VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name, |
| ExDeclType, TInfo, SC_None); |
| ExDecl->setExceptionVariable(true); |
| |
| // In ARC, infer 'retaining' for variables of retainable type. |
| if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl)) |
| Invalid = true; |
| |
| if (!Invalid && !ExDeclType->isDependentType()) { |
| if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) { |
| // Insulate this from anything else we might currently be parsing. |
| EnterExpressionEvaluationContext scope( |
| *this, ExpressionEvaluationContext::PotentiallyEvaluated); |
| |
| // C++ [except.handle]p16: |
| // The object declared in an exception-declaration or, if the |
| // exception-declaration does not specify a name, a temporary (12.2) is |
| // copy-initialized (8.5) from the exception object. [...] |
| // The object is destroyed when the handler exits, after the destruction |
| // of any automatic objects initialized within the handler. |
| // |
| // We just pretend to initialize the object with itself, then make sure |
| // it can be destroyed later. |
| QualType initType = Context.getExceptionObjectType(ExDeclType); |
| |
| InitializedEntity entity = |
| InitializedEntity::InitializeVariable(ExDecl); |
| InitializationKind initKind = |
| InitializationKind::CreateCopy(Loc, SourceLocation()); |
| |
| Expr *opaqueValue = |
| new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary); |
| InitializationSequence sequence(*this, entity, initKind, opaqueValue); |
| ExprResult result = sequence.Perform(*this, entity, initKind, opaqueValue); |
| if (result.isInvalid()) |
| Invalid = true; |
| else { |
| // If the constructor used was non-trivial, set this as the |
| // "initializer". |
| CXXConstructExpr *construct = result.getAs<CXXConstructExpr>(); |
| if (!construct->getConstructor()->isTrivial()) { |
| Expr *init = MaybeCreateExprWithCleanups(construct); |
| ExDecl->setInit(init); |
| } |
| |
| // And make sure it's destructable. |
| FinalizeVarWithDestructor(ExDecl, recordType); |
| } |
| } |
| } |
| |
| if (Invalid) |
| ExDecl->setInvalidDecl(); |
| |
| return ExDecl; |
| } |
| |
| /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch |
| /// handler. |
| Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { |
| TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); |
| bool Invalid = D.isInvalidType(); |
| |
| // Check for unexpanded parameter packs. |
| if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, |
| UPPC_ExceptionType)) { |
| TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy, |
| D.getIdentifierLoc()); |
| Invalid = true; |
| } |
| |
| IdentifierInfo *II = D.getIdentifier(); |
| if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(), |
| LookupOrdinaryName, |
| ForVisibleRedeclaration)) { |
| // The scope should be freshly made just for us. There is just no way |
| // it contains any previous declaration, except for function parameters in |
| // a function-try-block's catch statement. |
| assert(!S->isDeclScope(PrevDecl)); |
| if (isDeclInScope(PrevDecl, CurContext, S)) { |
| Diag(D.getIdentifierLoc(), diag::err_redefinition) |
| << D.getIdentifier(); |
| Diag(PrevDecl->getLocation(), diag::note_previous_definition); |
| Invalid = true; |
| } else if (PrevDecl->isTemplateParameter()) |
| // Maybe we will complain about the shadowed template parameter. |
| DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); |
| } |
| |
| if (D.getCXXScopeSpec().isSet() && !Invalid) { |
| Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator) |
| << D.getCXXScopeSpec().getRange(); |
| Invalid = true; |
| } |
| |
| VarDecl *ExDecl = BuildExceptionDeclaration(S, TInfo, |
| D.getLocStart(), |
| D.getIdentifierLoc(), |
| D.getIdentifier()); |
| if (Invalid) |
| ExDecl->setInvalidDecl(); |
| |
| // Add the exception declaration into this scope. |
| if (II) |
| PushOnScopeChains(ExDecl, S); |
| else |
| CurContext->addDecl(ExDecl); |
| |
| ProcessDeclAttributes(S, ExDecl, D); |
| return ExDecl; |
| } |
| |
| Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, |
| Expr *AssertExpr, |
| Expr *AssertMessageExpr, |
| SourceLocation RParenLoc) { |
| StringLiteral *AssertMessage = |
| AssertMessageExpr ? cast<StringLiteral>(AssertMessageExpr) : nullptr; |
| |
| if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression)) |
| return nullptr; |
| |
| return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr, |
| AssertMessage, RParenLoc, false); |
| } |
| |
| Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc, |
| Expr *AssertExpr, |
| StringLiteral *AssertMessage, |
| SourceLocation RParenLoc, |
| bool Failed) { |
| assert(AssertExpr != nullptr && "Expected non-null condition"); |
| if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() && |
| !Failed) { |
| // In a static_assert-declaration, the constant-expression shall be a |
| // constant expression that can be contextually converted to bool. |
| ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr); |
| if (Converted.isInvalid()) |
| Failed = true; |
| |
| llvm::APSInt Cond; |
| if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond, |
| diag::err_static_assert_expression_is_not_constant, |
| /*AllowFold=*/false).isInvalid()) |
| Failed = true; |
| |
| if (!Failed && !Cond) { |
| SmallString<256> MsgBuffer; |
| llvm::raw_svector_ostream Msg(MsgBuffer); |
| if (AssertMessage) |
| AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy()); |
| |
| Expr *InnerCond = nullptr; |
| std::string InnerCondDescription; |
| std::tie(InnerCond, InnerCondDescription) = |
| findFailedBooleanCondition(Converted.get(), |
| /*AllowTopLevelCond=*/false); |
| if (InnerCond) { |
| Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed) |
| << InnerCondDescription << !AssertMessage |
| << Msg.str() << InnerCond->getSourceRange(); |
| } else { |
| Diag(StaticAssertLoc, diag::err_static_assert_failed) |
| << !AssertMessage << Msg.str() << AssertExpr->getSourceRange(); |
| } |
| Failed = true; |
| } |
| } |
| |
| ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc, |
| /*DiscardedValue*/false, |
| /*IsConstexpr*/true); |
| if (FullAssertExpr.isInvalid()) |
| Failed = true; |
| else |
| AssertExpr = FullAssertExpr.get(); |
| |
| Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc, |
| AssertExpr, AssertMessage, RParenLoc, |
| Failed); |
| |
| CurContext->addDecl(Decl); |
| return Decl; |
| } |
| |
| /// Perform semantic analysis of the given friend type declaration. |
| /// |
| /// \returns A friend declaration that. |
| FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, |
| SourceLocation FriendLoc, |
| TypeSourceInfo *TSInfo) { |
| assert(TSInfo && "NULL TypeSourceInfo for friend type declaration"); |
| |
| QualType T = TSInfo->getType(); |
| SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange(); |
| |
| // C++03 [class.friend]p2: |
| // An elaborated-type-specifier shall be used in a friend declaration |
| // for a class.* |
| // |
| // * The class-key of the elaborated-type-specifier is required. |
| if (!CodeSynthesisContexts.empty()) { |
| // Do not complain about the form of friend template types during any kind |
| // of code synthesis. For template instantiation, we will have complained |
| // when the template was defined. |
| } else { |
| if (!T->isElaboratedTypeSpecifier()) { |
| // If we evaluated the type to a record type, suggest putting |
| // a tag in front. |
| if (const RecordType *RT = T->getAs<RecordType>()) { |
| RecordDecl *RD = RT->getDecl(); |
| |
| SmallString<16> InsertionText(" "); |
| InsertionText += RD->getKindName(); |
| |
| Diag(TypeRange.getBegin(), |
| getLangOpts().CPlusPlus11 ? |
| diag::warn_cxx98_compat_unelaborated_friend_type : |
| diag::ext_unelaborated_friend_type) |
| << (unsigned) RD->getTagKind() |
| << T |
| << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc), |
| InsertionText); |
| } else { |
| Diag(FriendLoc, |
| getLangOpts().CPlusPlus11 ? |
| diag::warn_cxx98_compat_nonclass_type_friend : |
| diag::ext_nonclass_type_friend) |
| << T |
| << TypeRange; |
| } |
| } else if (T->getAs<EnumType>()) { |
| Diag(FriendLoc, |
| getLangOpts().CPlusPlus11 ? |
| diag::warn_cxx98_compat_enum_friend : |
| diag::ext_enum_friend) |
| << T |
| << TypeRange; |
| } |
| |
| // C++11 [class.friend]p3: |
| // A friend declaration that does not declare a function shall have one |
| // of the following forms: |
| // friend elaborated-type-specifier ; |
| // friend simple-type-specifier ; |
| // friend typename-specifier ; |
| if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc) |
| Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T; |
| } |
| |
| // If the type specifier in a friend declaration designates a (possibly |
| // cv-qualified) class type, that class is declared as a friend; otherwise, |
| // the friend declaration is ignored. |
| return FriendDecl::Create(Context, CurContext, |
| TSInfo->getTypeLoc().getLocStart(), TSInfo, |
| FriendLoc); |
| } |
| |
| /// Handle a friend tag declaration where the scope specifier was |
| /// templated. |
| Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, |
| unsigned TagSpec, SourceLocation TagLoc, |
| CXXScopeSpec &SS, IdentifierInfo *Name, |
| SourceLocation NameLoc, |
| const ParsedAttributesView &Attr, |
| MultiTemplateParamsArg TempParamLists) { |
| TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); |
| |
| bool IsMemberSpecialization = false; |
| bool Invalid = false; |
| |
| if (TemplateParameterList *TemplateParams = |
| MatchTemplateParametersToScopeSpecifier( |
| TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true, |
| IsMemberSpecialization, Invalid)) { |
| if (TemplateParams->size() > 0) { |
| // This is a declaration of a class template. |
| if (Invalid) |
| return nullptr; |
| |
| return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name, |
| NameLoc, Attr, TemplateParams, AS_public, |
| /*ModulePrivateLoc=*/SourceLocation(), |
| FriendLoc, TempParamLists.size() - 1, |
| TempParamLists.data()).get(); |
| } else { |
| // The "template<>" header is extraneous. |
| Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) |
| << TypeWithKeyword::getTagTypeKindName(Kind) << Name; |
| IsMemberSpecialization = true; |
| } |
| } |
| |
| if (Invalid) return nullptr; |
| |
| bool isAllExplicitSpecializations = true; |
| for (unsigned I = TempParamLists.size(); I-- > 0; ) { |
| if (TempParamLists[I]->size()) { |
| isAllExplicitSpecializations = false; |
| break; |
| } |
| } |
| |
| // FIXME: don't ignore attributes. |
| |
| // If it's explicit specializations all the way down, just forget |
| // about the template header and build an appropriate non-templated |
| // friend. TODO: for source fidelity, remember the headers. |
| if (isAllExplicitSpecializations) { |
| if (SS.isEmpty()) { |
| bool Owned = false; |
| bool IsDependent = false; |
| return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc, |
| Attr, AS_public, |
| /*ModulePrivateLoc=*/SourceLocation(), |
| MultiTemplateParamsArg(), Owned, IsDependent, |
| /*ScopedEnumKWLoc=*/SourceLocation(), |
| /*ScopedEnumUsesClassTag=*/false, |
| /*UnderlyingType=*/TypeResult(), |
| /*IsTypeSpecifier=*/false, |
| /*IsTemplateParamOrArg=*/false); |
| } |
| |
| NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); |
| ElaboratedTypeKeyword Keyword |
| = TypeWithKeyword::getKeywordForTagTypeKind(Kind); |
| QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc, |
| *Name, NameLoc); |
| if (T.isNull()) |
| return nullptr; |
| |
| TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); |
| if (isa<DependentNameType>(T)) { |
| DependentNameTypeLoc TL = |
| TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); |
| TL.setElaboratedKeywordLoc(TagLoc); |
| TL.setQualifierLoc(QualifierLoc); |
| TL.setNameLoc(NameLoc); |
| } else { |
| ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>(); |
| TL.setElaboratedKeywordLoc(TagLoc); |
| TL.setQualifierLoc(QualifierLoc); |
| TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc); |
| } |
| |
| FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, |
| TSI, FriendLoc, TempParamLists); |
| Friend->setAccess(AS_public); |
| CurContext->addDecl(Friend); |
| return Friend; |
| } |
| |
| assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?"); |
| |
| |
| |
| // Handle the case of a templated-scope friend class. e.g. |
| // template <class T> class A<T>::B; |
| // FIXME: we don't support these right now. |
| Diag(NameLoc, diag::warn_template_qualified_friend_unsupported) |
| << SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext); |
| ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); |
| QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); |
| TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); |
| DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>(); |
| TL.setElaboratedKeywordLoc(TagLoc); |
| TL.setQualifierLoc(SS.getWithLocInContext(Context)); |
| TL.setNameLoc(NameLoc); |
| |
| FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc, |
| TSI, FriendLoc, TempParamLists); |
| Friend->setAccess(AS_public); |
| Friend->setUnsupportedFriend(true); |
| CurContext->addDecl(Friend); |
| return Friend; |
| } |
| |
| /// Handle a friend type declaration. This works in tandem with |
| /// ActOnTag. |
| /// |
| /// Notes on friend class templates: |
| /// |
| /// We generally treat friend class declarations as if they were |
| /// declaring a class. So, for example, the elaborated type specifier |
| /// in a friend declaration is required to obey the restrictions of a |
| /// class-head (i.e. no typedefs in the scope chain), template |
| /// parameters are required to match up with simple template-ids, &c. |
| /// However, unlike when declaring a template specialization, it's |
| /// okay to refer to a template specialization without an empty |
| /// template parameter declaration, e.g. |
| /// friend class A<T>::B<unsigned>; |
| /// We permit this as a special case; if there are any template |
| /// parameters present at all, require proper matching, i.e. |
| /// template <> template \<class T> friend class A<int>::B; |
| Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS, |
| MultiTemplateParamsArg TempParams) { |
| SourceLocation Loc = DS.getLocStart(); |
| |
| assert(DS.isFriendSpecified()); |
| assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); |
| |
| // Try to convert the decl specifier to a type. This works for |
| // friend templates because ActOnTag never produces a ClassTemplateDecl |
| // for a TUK_Friend. |
| Declarator TheDeclarator(DS, DeclaratorContext::MemberContext); |
| TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S); |
| QualType T = TSI->getType(); |
| if (TheDeclarator.isInvalidType()) |
| return nullptr; |
| |
| if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration)) |
| return nullptr; |
| |
| // This is definitely an error in C++98. It's probably meant to |
| // be forbidden in C++0x, too, but the specification is just |
| // poorly written. |
| // |
| // The problem is with declarations like the following: |
| // template <T> friend A<T>::foo; |
| // where deciding whether a class C is a friend or not now hinges |
| // on whether there exists an instantiation of A that causes |
| // 'foo' to equal C. There are restrictions on class-heads |
| // (which we declare (by fiat) elaborated friend declarations to |
| // be) that makes this tractable. |
| // |
| // FIXME: handle "template <> friend class A<T>;", which |
| // is possibly well-formed? Who even knows? |
| if (TempParams.size() && !T->isElaboratedTypeSpecifier()) { |
| Diag(Loc, diag::err_tagless_friend_type_template) |
| << DS.getSourceRange(); |
| return nullptr; |
| } |
| |
| // C++98 [class.friend]p1: A friend of a class is a function |
| // or class that is not a member of the class . . . |
| // This is fixed in DR77, which just barely didn't make the C++03 |
| // deadline. It's also a very silly restriction that seriously |
| // affects inner classes and which nobody else seems to implement; |
| // thus we never diagnose it, not even in -pedantic. |
| // |
| // But note that we could warn about it: it's always useless to |
| // friend one of your own members (it's not, however, worthless to |
| // friend a member of an arbitrary specialization of your template). |
| |
| Decl *D; |
| if (!TempParams.empty()) |
| D = FriendTemplateDecl::Create(Context, CurContext, Loc, |
| TempParams, |
| TSI, |
| DS.getFriendSpecLoc()); |
| else |
| D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI); |
| |
| if (!D) |
| return nullptr; |
| |
| D->setAccess(AS_public); |
| CurContext->addDecl(D); |
| |
| return D; |
| } |
| |
| NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, |
| MultiTemplateParamsArg TemplateParams) { |
| const DeclSpec &DS = D.getDeclSpec(); |
| |
| assert(DS.isFriendSpecified()); |
| assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified); |
| |
| SourceLocation Loc = D.getIdentifierLoc(); |
| TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); |
| |
| // C++ [class.friend]p1 |
| // A friend of a class is a function or class.... |
| // Note that this sees through typedefs, which is intended. |
| // It *doesn't* see through dependent types, which is correct |
| // according to [temp.arg.type]p3: |
| // If a declaration acquires a function type through a |
| // type dependent on a template-parameter and this causes |
| // a declaration that does not use the syntactic form of a |
| // function declarator to have a function type, the program |
| // is ill-formed. |
| if (!TInfo->getType()->isFunctionType()) { |
| Diag(Loc, diag::err_unexpected_friend); |
| |
| // It might be worthwhile to try to recover by creating an |
| // appropriate declaration. |
| return nullptr; |
| } |
| |
| // C++ [namespace.memdef]p3 |
| // - If a friend declaration in a non-local class first declares a |
| // class or function, the friend class or function is a member |
| // of the innermost enclosing namespace. |
| // - The name of the friend is not found by simple name lookup |
| // until a matching declaration is provided in that namespace |
| // scope (either before or after the class declaration granting |
| // friendship). |
| // - If a friend function is called, its name may be found by the |
| // name lookup that considers functions from namespaces and |
| // classes associated with the types of the function arguments. |
| // - When looking for a prior declaration of a class or a function |
| // declared as a friend, scopes outside the innermost enclosing |
| // namespace scope are not considered. |
| |
| CXXScopeSpec &SS = D.getCXXScopeSpec(); |
| DeclarationNameInfo NameInfo = GetNameForDeclarator(D); |
| DeclarationName Name = NameInfo.getName(); |
| assert(Name); |
| |
| // Check for unexpanded parameter packs. |
| if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) || |
| DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) || |
| DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration)) |
| return nullptr; |
| |
| // The context we found the declaration in, or in which we should |
| // create the declaration. |
| DeclContext *DC; |
| Scope *DCScope = S; |
| LookupResult Previous(*this, NameInfo, LookupOrdinaryName, |
| ForExternalRedeclaration); |
| |
| // There are five cases here. |
| // - There's no scope specifier and we're in a local class. Only look |
| // for functions declared in the immediately-enclosing block scope. |
| // We recover from invalid scope qualifiers as if they just weren't there. |
| FunctionDecl *FunctionContainingLocalClass = nullptr; |
| if ((SS.isInvalid() || !SS.isSet()) && |
| (FunctionContainingLocalClass = |
| cast<CXXRecordDecl>(CurContext)->isLocalClass())) { |
| // C++11 [class.friend]p11: |
| // If a friend declaration appears in a local class and the name |
| // specified is an unqualified name, a prior declaration is |
| // looked up without considering scopes that are outside the |
| // innermost enclosing non-class scope. For a friend function |
| // declaration, if there is no prior declaration, the program is |
| // ill-formed. |
| |
| // Find the innermost enclosing non-class scope. This is the block |
| // scope containing the local class definition (or for a nested class, |
| // the outer local class). |
| DCScope = S->getFnParent(); |
| |
| // Look up the function name in the scope. |
| Previous.clear(LookupLocalFriendName); |
| LookupName(Previous, S, /*AllowBuiltinCreation*/false); |
| |
| if (!Previous.empty()) { |
| // All possible previous declarations must have the same context: |
| // either they were declared at block scope or they are members of |
| // one of the enclosing local classes. |
| DC = Previous.getRepresentativeDecl()->getDeclContext(); |
| } else { |
| // This is ill-formed, but provide the context that we would have |
| // declared the function in, if we were permitted to, for error recovery. |
| DC = FunctionContainingLocalClass; |
| } |
| adjustContextForLocalExternDecl(DC); |
| |
| // C++ [class.friend]p6: |
| // A function can be defined in a friend declaration of a class if and |
| // only if the class is a non-local class (9.8), the function name is |
| // unqualified, and the function has namespace scope. |
| if (D.isFunctionDefinition()) { |
| Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class); |
| } |
| |
| // - There's no scope specifier, in which case we just go to the |
| // appropriate scope and look for a function or function template |
| // there as appropriate. |
| } else if (SS.isInvalid() || !SS.isSet()) { |
| // C++11 [namespace.memdef]p3: |
| // If the name in a friend declaration is neither qualified nor |
| // a template-id and the declaration is a function or an |
| // elaborated-type-specifier, the lookup to determine whether |
| // the entity has been previously declared shall not consider |
| // any scopes outside the innermost enclosing namespace. |
| bool isTemplateId = |
| D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId; |
| |
| // Find the appropriate context according to the above. |
| DC = CurContext; |
| |
| // Skip class contexts. If someone can cite chapter and verse |
| // for this behavior, that would be nice --- it's what GCC and |
| // EDG do, and it seems like a reasonable intent, but the spec |
| // really only says that checks for unqualified existing |
| // declarations should stop at the nearest enclosing namespace, |
| // not that they should only consider the nearest enclosing |
| // namespace. |
| while (DC->isRecord()) |
| DC = DC->getParent(); |
| |
| DeclContext *LookupDC = DC; |
| while (LookupDC->isTransparentContext()) |
| LookupDC = LookupDC->getParent(); |
| |
| while (true) { |
| LookupQualifiedName(Previous, LookupDC); |
| |
| if (!Previous.empty()) { |
| DC = LookupDC; |
| break; |
| } |
| |
| if (isTemplateId) { |
| if (isa<TranslationUnitDecl>(LookupDC)) break; |
| } else { |
| if (LookupDC->isFileContext()) break; |
| } |
| LookupDC = LookupDC->getParent(); |
| } |
| |
| DCScope = getScopeForDeclContext(S, DC); |
| |
| // - There's a non-dependent scope specifier, in which case we |
| // compute it and do a previous lookup there for a function |
| // or function template. |
| } else if (!SS.getScopeRep()->isDependent()) { |
| DC = computeDeclContext(SS); |
| if (!DC) return nullptr; |
| |
| if (RequireCompleteDeclContext(SS, DC)) return nullptr; |
| |
| LookupQualifiedName(Previous, DC); |
| |
| // Ignore things found implicitly in the wrong scope. |
| // TODO: better diagnostics for this case. Suggesting the right |
| // qualified scope would be nice... |
| LookupResult::Filter F = Previous.makeFilter(); |
| while (F.hasNext()) { |
| NamedDecl *D = F.next(); |
| if (!DC->InEnclosingNamespaceSetOf( |
| D->getDeclContext()->getRedeclContext())) |
| F.erase(); |
| } |
| F.done(); |
| |
| if (Previous.empty()) { |
| D.setInvalidType(); |
| Diag(Loc, diag::err_qualified_friend_not_found) |
| << Name << TInfo->getType(); |
| return nullptr; |
| } |
| |
| // C++ [class.friend]p1: A friend of a class is a function or |
| // class that is not a member of the class . . . |
| if (DC->Equals(CurContext)) |
| Diag(DS.getFriendSpecLoc(), |
| getLangOpts().CPlusPlus11 ? |
| diag::warn_cxx98_compat_friend_is_member : |
| diag::err_friend_is_member); |
| |
| if (D.isFunctionDefinition()) { |
| // C++ [class.friend]p6: |
| // A function can be defined in a friend declaration of a class if and |
| // only if the class is a non-local class (9.8), the function name is |
| // unqualified, and the function has namespace scope. |
| SemaDiagnosticBuilder DB |
| = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def); |
| |
| DB << SS.getScopeRep(); |
| if (DC->isFileContext()) |
| DB << FixItHint::CreateRemoval(SS.getRange()); |
| SS.clear(); |
| } |
| |
| // - There's a scope specifier that does not match any template |
| // parameter lists, in which case we use some arbitrary context, |
| // create a method or method template, and wait for instantiation. |
| // - There's a scope specifier that does match some template |
| // parameter lists, which we don't handle right now. |
| } else { |
| if (D.isFunctionDefinition()) { |
| // C++ [class.friend]p6: |
| // A function can be defined in a friend declaration of a class if and |
| // only if the class is a non-local class (9.8), the function name is |
| // unqualified, and the function has namespace scope. |
| Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def) |
| << SS.getScopeRep(); |
| } |
| |
| DC = CurContext; |
| assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?"); |
| } |
| |
| if (!DC->isRecord()) { |
| int DiagArg = -1; |
| switch (D.getName().getKind()) { |
| case UnqualifiedIdKind::IK_ConstructorTemplateId: |
| case UnqualifiedIdKind::IK_ConstructorName: |
| DiagArg = 0; |
| break; |
| case UnqualifiedIdKind::IK_DestructorName: |
| DiagArg = 1; |
| break; |
| case UnqualifiedIdKind::IK_ConversionFunctionId: |
| DiagArg = 2; |
| break; |
| case UnqualifiedIdKind::IK_DeductionGuideName: |
| DiagArg = 3; |
| break; |
| case UnqualifiedIdKind::IK_Identifier: |
| case UnqualifiedIdKind::IK_ImplicitSelfParam: |
| case UnqualifiedIdKind::IK_LiteralOperatorId: |
| case UnqualifiedIdKind::IK_OperatorFunctionId: |
| case UnqualifiedIdKind::IK_TemplateId: |
| break; |
| } |
| // This implies that it has to be an operator or function. |
| if (DiagArg >= 0) { |
| Diag(Loc, diag::err_introducing_special_friend) << DiagArg; |
| return nullptr; |
| } |
| } |
| |
| // FIXME: This is an egregious hack to cope with cases where the scope stack |
| // does not contain the declaration context, i.e., in an out-of-line |
| // definition of a class. |
| Scope FakeDCScope(S, Scope::DeclScope, Diags); |
| if (!DCScope) { |
| FakeDCScope.setEntity(DC); |
| DCScope = &FakeDCScope; |
| } |
| |
| bool AddToScope = true; |
| NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous, |
| TemplateParams, AddToScope); |
| if (!ND) return nullptr; |
| |
| assert(ND->getLexicalDeclContext() == CurContext); |
| |
| // If we performed typo correction, we might have added a scope specifier |
| // and changed the decl context. |
| DC = ND->getDeclContext(); |
| |
| // Add the function declaration to the appropriate lookup tables, |
| // adjusting the redeclarations list as necessary. We don't |
| // want to do this yet if the friending class is dependent. |
| // |
| // Also update the scope-based lookup if the target context's |
| // lookup context is in lexical scope. |
| if (!CurContext->isDependentContext()) { |
| DC = DC->getRedeclContext(); |
| DC->makeDeclVisibleInContext(ND); |
| if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) |
| PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false); |
| } |
| |
| FriendDecl *FrD = FriendDecl::Create(Context, CurContext, |
| D.getIdentifierLoc(), ND, |
| DS.getFriendSpecLoc()); |
| FrD->setAccess(AS_public); |
| CurContext->addDecl(FrD); |
| |
| if (ND->isInvalidDecl()) { |
| FrD->setInvalidDecl(); |
| } else { |
| if (DC->isRecord()) CheckFriendAccess(ND); |
| |
| FunctionDecl *FD; |
| if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) |
| FD = FTD->getTemplatedDecl(); |
| else |
| FD = cast<FunctionDecl>(ND); |
| |
| // 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 (functionDeclHasDefaultArgument(FD)) { |
| // We can't look at FD->getPreviousDecl() because it may not have been set |
| // if we're in a dependent context. If the function is known to be a |
| // redeclaration, we will have narrowed Previous down to the right decl. |
| if (D.isRedeclaration()) { |
| Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared); |
| Diag(Previous.getRepresentativeDecl()->getLocation(), |
| diag::note_previous_declaration); |
| } else if (!D.isFunctionDefinition()) |
| Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def); |
| } |
| |
| // Mark templated-scope function declarations as unsupported. |
| if (FD->getNumTemplateParameterLists() && SS.isValid()) { |
| Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported) |
| << SS.getScopeRep() << SS.getRange() |
| << cast<CXXRecordDecl>(CurContext); |
| FrD->setUnsupportedFriend(true); |
| } |
| } |
| |
| return ND; |
| } |
| |
| void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) { |
| AdjustDeclIfTemplate(Dcl); |
| |
| FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl); |
| if (!Fn) { |
| Diag(DelLoc, diag::err_deleted_non_function); |
| return; |
| } |
| |
| // Deleted function does not have a body. |
| Fn->setWillHaveBody(false); |
| |
| if (const FunctionDecl *Prev = Fn->getPreviousDecl()) { |
| // Don't consider the implicit declaration we generate for explicit |
| // specializations. FIXME: Do not generate these implicit declarations. |
| if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization || |
| Prev->getPreviousDecl()) && |
| !Prev->isDefined()) { |
| Diag(DelLoc, diag::err_deleted_decl_not_first); |
| Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(), |
| Prev->isImplicit() ? diag::note_previous_implicit_declaration |
| : diag::note_previous_declaration); |
| } |
| // If the declaration wasn't the first, we delete the function anyway for |
| // recovery. |
| Fn = Fn->getCanonicalDecl(); |
| } |
| |
| // dllimport/dllexport cannot be deleted. |
| if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) { |
| Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr; |
| Fn->setInvalidDecl(); |
| } |
| |
| if (Fn->isDeleted()) |
| return; |
| |
| // See if we're deleting a function which is already known to override a |
| // non-deleted virtual function. |
| if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) { |
| bool IssuedDiagnostic = false; |
| for (const CXXMethodDecl *O : MD->overridden_methods()) { |
| if (!(*MD->begin_overridden_methods())->isDeleted()) { |
| if (!IssuedDiagnostic) { |
| Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName(); |
| IssuedDiagnostic = true; |
| } |
| Diag(O->getLocation(), diag::note_overridden_virtual_function); |
| } |
| } |
| // If this function was implicitly deleted because it was defaulted, |
| // explain why it was deleted. |
| if (IssuedDiagnostic && MD->isDefaulted()) |
| ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr, |
| /*Diagnose*/true); |
| } |
| |
| // C++11 [basic.start.main]p3: |
| // A program that defines main as deleted [...] is ill-formed. |
| if (Fn->isMain()) |
| Diag(DelLoc, diag::err_deleted_main); |
| |
| // C++11 [dcl.fct.def.delete]p4: |
| // A deleted function is implicitly inline. |
| Fn->setImplicitlyInline(); |
| Fn->setDeletedAsWritten(); |
| } |
| |
| void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) { |
| CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl); |
| |
| if (MD) { |
| if (MD->getParent()->isDependentType()) { |
| MD->setDefaulted(); |
| MD->setExplicitlyDefaulted(); |
| return; |
| } |
| |
| CXXSpecialMember Member = getSpecialMember(MD); |
| if (Member == CXXInvalid) { |
| if (!MD->isInvalidDecl()) |
| Diag(DefaultLoc, diag::err_default_special_members); |
| return; |
| } |
| |
| MD->setDefaulted(); |
| MD->setExplicitlyDefaulted(); |
| |
| // Unset that we will have a body for this function. We might not, |
| // if it turns out to be trivial, and we don't need this marking now |
| // that we've marked it as defaulted. |
| MD->setWillHaveBody(false); |
| |
| // If this definition appears within the record, do the checking when |
| // the record is complete. |
| const FunctionDecl *Primary = MD; |
| if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern()) |
| // Ask the template instantiation pattern that actually had the |
| // '= default' on it. |
| Primary = Pattern; |
| |
| // If the method was defaulted on its first declaration, we will have |
| // already performed the checking in CheckCompletedCXXClass. Such a |
| // declaration doesn't trigger an implicit definition. |
| if (Primary->getCanonicalDecl()->isDefaulted()) |
| return; |
| |
| CheckExplicitlyDefaultedSpecialMember(MD); |
| |
| if (!MD->isInvalidDecl()) |
| DefineImplicitSpecialMember(*this, MD, DefaultLoc); |
| } else { |
| Diag(DefaultLoc, diag::err_default_special_members); |
| } |
| } |
| |
| static void SearchForReturnInStmt(Sema &Self, Stmt *S) { |
| for (Stmt *SubStmt : S->children()) { |
| if (!SubStmt) |
| continue; |
| if (isa<ReturnStmt>(SubStmt)) |
| Self.Diag(SubStmt->getLocStart(), |
| diag::err_return_in_constructor_handler); |
| if (!isa<Expr>(SubStmt)) |
| SearchForReturnInStmt(Self, SubStmt); |
| } |
| } |
| |
| void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) { |
| for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) { |
| CXXCatchStmt *Handler = TryBlock->getHandler(I); |
| SearchForReturnInStmt(*this, Handler); |
| } |
| } |
| |
| bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New, |
| const CXXMethodDecl *Old) { |
| const auto *NewFT = New->getType()->getAs<FunctionProtoType>(); |
| const auto *OldFT = Old->getType()->getAs<FunctionProtoType>(); |
| |
| if (OldFT->hasExtParameterInfos()) { |
| for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I) |
| // A parameter of the overriding method should be annotated with noescape |
| // if the corresponding parameter of the overridden method is annotated. |
| if (OldFT->getExtParameterInfo(I).isNoEscape() && |
| !NewFT->getExtParameterInfo(I).isNoEscape()) { |
| Diag(New->getParamDecl(I)->getLocation(), |
| diag::warn_overriding_method_missing_noescape); |
| Diag(Old->getParamDecl(I)->getLocation(), |
| diag::note_overridden_marked_noescape); |
| } |
| } |
| |
| // Virtual overrides must have the same code_seg. |
| const auto *OldCSA = Old->getAttr<CodeSegAttr>(); |
| const auto *NewCSA = New->getAttr<CodeSegAttr>(); |
| if ((NewCSA || OldCSA) && |
| (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) { |
| Diag(New->getLocation(), diag::err_mismatched_code_seg_override); |
| Diag(Old->getLocation(), diag::note_previous_declaration); |
| return true; |
| } |
| |
| CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv(); |
| |
| // If the calling conventions match, everything is fine |
| if (NewCC == OldCC) |
| return false; |
| |
| // If the calling conventions mismatch because the new function is static, |
| // suppress the calling convention mismatch error; the error about static |
| // function override (err_static_overrides_virtual from |
| // Sema::CheckFunctionDeclaration) is more clear. |
| if (New->getStorageClass() == SC_Static) |
| return false; |
| |
| Diag(New->getLocation(), |
| diag::err_conflicting_overriding_cc_attributes) |
| << New->getDeclName() << New->getType() << Old->getType(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function); |
| return true; |
| } |
| |
| bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New, |
| const CXXMethodDecl *Old) { |
| QualType NewTy = New->getType()->getAs<FunctionType>()->getReturnType(); |
| QualType OldTy = Old->getType()->getAs<FunctionType>()->getReturnType(); |
| |
| if (Context.hasSameType(NewTy, OldTy) || |
| NewTy->isDependentType() || OldTy->isDependentType()) |
| return false; |
| |
| // Check if the return types are covariant |
| QualType NewClassTy, OldClassTy; |
| |
| /// Both types must be pointers or references to classes. |
| if (const PointerType *NewPT = NewTy->getAs<PointerType>()) { |
| if (const PointerType *OldPT = OldTy->getAs<PointerType>()) { |
| NewClassTy = NewPT->getPointeeType(); |
| OldClassTy = OldPT->getPointeeType(); |
| } |
| } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) { |
| if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) { |
| if (NewRT->getTypeClass() == OldRT->getTypeClass()) { |
| NewClassTy = NewRT->getPointeeType(); |
| OldClassTy = OldRT->getPointeeType(); |
| } |
| } |
| } |
| |
| // The return types aren't either both pointers or references to a class type. |
| if (NewClassTy.isNull()) { |
| Diag(New->getLocation(), |
| diag::err_different_return_type_for_overriding_virtual_function) |
| << New->getDeclName() << NewTy << OldTy |
| << New->getReturnTypeSourceRange(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function) |
| << Old->getReturnTypeSourceRange(); |
| |
| return true; |
| } |
| |
| if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) { |
| // C++14 [class.virtual]p8: |
| // If the class type in the covariant return type of D::f differs from |
| // that of B::f, the class type in the return type of D::f shall be |
| // complete at the point of declaration of D::f or shall be the class |
| // type D. |
| if (const RecordType *RT = NewClassTy->getAs<RecordType>()) { |
| if (!RT->isBeingDefined() && |
| RequireCompleteType(New->getLocation(), NewClassTy, |
| diag::err_covariant_return_incomplete, |
| New->getDeclName())) |
| return true; |
| } |
| |
| // Check if the new class derives from the old class. |
| if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) { |
| Diag(New->getLocation(), diag::err_covariant_return_not_derived) |
| << New->getDeclName() << NewTy << OldTy |
| << New->getReturnTypeSourceRange(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function) |
| << Old->getReturnTypeSourceRange(); |
| return true; |
| } |
| |
| // Check if we the conversion from derived to base is valid. |
| if (CheckDerivedToBaseConversion( |
| NewClassTy, OldClassTy, |
| diag::err_covariant_return_inaccessible_base, |
| diag::err_covariant_return_ambiguous_derived_to_base_conv, |
| New->getLocation(), New->getReturnTypeSourceRange(), |
| New->getDeclName(), nullptr)) { |
| // FIXME: this note won't trigger for delayed access control |
| // diagnostics, and it's impossible to get an undelayed error |
| // here from access control during the original parse because |
| // the ParsingDeclSpec/ParsingDeclarator are still in scope. |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function) |
| << Old->getReturnTypeSourceRange(); |
| return true; |
| } |
| } |
| |
| // The qualifiers of the return types must be the same. |
| if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) { |
| Diag(New->getLocation(), |
| diag::err_covariant_return_type_different_qualifications) |
| << New->getDeclName() << NewTy << OldTy |
| << New->getReturnTypeSourceRange(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function) |
| << Old->getReturnTypeSourceRange(); |
| return true; |
| } |
| |
| |
| // The new class type must have the same or less qualifiers as the old type. |
| if (NewClassTy.isMoreQualifiedThan(OldClassTy)) { |
| Diag(New->getLocation(), |
| diag::err_covariant_return_type_class_type_more_qualified) |
| << New->getDeclName() << NewTy << OldTy |
| << New->getReturnTypeSourceRange(); |
| Diag(Old->getLocation(), diag::note_overridden_virtual_function) |
| << Old->getReturnTypeSourceRange(); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Mark the given method pure. |
| /// |
| /// \param Method the method to be marked pure. |
| /// |
| /// \param InitRange the source range that covers the "0" initializer. |
| bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { |
| SourceLocation EndLoc = InitRange.getEnd(); |
| if (EndLoc.isValid()) |
| Method->setRangeEnd(EndLoc); |
| |
| if (Method->isVirtual() || Method->getParent()->isDependentContext()) { |
| Method->setPure(); |
| return false; |
| } |
| |
| if (!Method->isInvalidDecl()) |
| Diag(Method->getLocation(), diag::err_non_virtual_pure) |
| << Method->getDeclName() << InitRange; |
| return true; |
| } |
| |
| void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) { |
| if (D->getFriendObjectKind()) |
| Diag(D->getLocation(), diag::err_pure_friend); |
| else if (auto *M = dyn_cast<CXXMethodDecl>(D)) |
| CheckPureMethod(M, ZeroLoc); |
| else |
| Diag(D->getLocation(), diag::err_illegal_initializer); |
| } |
| |
| /// Determine whether the given declaration is a global variable or |
| /// static data member. |
| static bool isNonlocalVariable(const Decl *D) { |
| if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D)) |
| return Var->hasGlobalStorage(); |
| |
| return false; |
| } |
| |
| /// Invoked when we are about to parse an initializer for the declaration |
| /// 'Dcl'. |
| /// |
| /// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a |
| /// static data member of class X, names should be looked up in the scope of |
| /// class X. If the declaration had a scope specifier, a scope will have |
| /// been created and passed in for this purpose. Otherwise, S will be null. |
| void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { |
| // If there is no declaration, there was an error parsing it. |
| if (!D || D->isInvalidDecl()) |
| return; |
| |
| // We will always have a nested name specifier here, but this declaration |
| // might not be out of line if the specifier names the current namespace: |
| // extern int n; |
| // int ::n = 0; |
| if (S && D->isOutOfLine()) |
| EnterDeclaratorContext(S, D->getDeclContext()); |
| |
| // If we are parsing the initializer for a static data member, push a |
| // new expression evaluation context that is associated with this static |
| // data member. |
| if (isNonlocalVariable(D)) |
| PushExpressionEvaluationContext( |
| ExpressionEvaluationContext::PotentiallyEvaluated, D); |
| } |
| |
| /// Invoked after we are finished parsing an initializer for the declaration D. |
| void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { |
| // If there is no declaration, there was an error parsing it. |
| if (!D || D->isInvalidDecl()) |
| return; |
| |
| if (isNonlocalVariable(D)) |
| PopExpressionEvaluationContext(); |
| |
| if (S && D->isOutOfLine()) |
| ExitDeclaratorContext(S); |
| } |
| |
| /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a |
| /// C++ if/switch/while/for statement. |
| /// e.g: "if (int x = f()) {...}" |
| DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) { |
| // C++ 6.4p2: |
| // The declarator shall not specify a function or an array. |
| // The type-specifier-seq shall not contain typedef and shall not declare a |
| // new class or enumeration. |
| assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && |
| "Parser allowed 'typedef' as storage class of condition decl."); |
| |
| Decl *Dcl = ActOnDeclarator(S, D); |
| if (!Dcl) |
| return true; |
| |
| if (isa<FunctionDecl>(Dcl)) { // The declarator shall not specify a function. |
| Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type) |
| << D.getSourceRange(); |
| return true; |
| } |
| |
| return Dcl; |
| } |
| |
| void Sema::LoadExternalVTableUses() { |
| if (!ExternalSource) |
| return; |
| |
| SmallVector<ExternalVTableUse, 4> VTables; |
| ExternalSource->ReadUsedVTables(VTables); |
| SmallVector<VTableUse, 4> NewUses; |
| for (unsigned I = 0, N = VTables.size(); I != N; ++I) { |
| llvm::DenseMap<CXXRecordDecl *, bool>::iterator Pos |
| = VTablesUsed.find(VTables[I].Record); |
| // Even if a definition wasn't required before, it may be required now. |
| if (Pos != VTablesUsed.end()) { |
| if (!Pos->second && VTables[I].DefinitionRequired) |
| Pos->second = true; |
| continue; |
| } |
| |
| VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired; |
| NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location)); |
| } |
| |
| VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end()); |
| } |
| |
| void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, |
| bool DefinitionRequired) { |
| // Ignore any vtable uses in unevaluated operands or for classes that do |
| // not have a vtable. |
| if (!Class->isDynamicClass() || Class->isDependentContext() || |
| CurContext->isDependentContext() || isUnevaluatedContext()) |
| return; |
| |
| // Try to insert this class into the map. |
| LoadExternalVTableUses(); |
| Class = Class->getCanonicalDecl(); |
| std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool> |
| Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired)); |
| if (!Pos.second) { |
| // If we already had an entry, check to see if we are promoting this vtable |
| // to require a definition. If so, we need to reappend to the VTableUses |
| // list, since we may have already processed the first entry. |
| if (DefinitionRequired && !Pos.first->second) { |
| Pos.first->second = true; |
| } else { |
| // Otherwise, we can early exit. |
| return; |
| } |
| } else { |
| // The Microsoft ABI requires that we perform the destructor body |
| // checks (i.e. operator delete() lookup) when the vtable is marked used, as |
| // the deleting destructor is emitted with the vtable, not with the |
| // destructor definition as in the Itanium ABI. |
| if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { |
| CXXDestructorDecl *DD = Class->getDestructor(); |
| if (DD && DD->isVirtual() && !DD->isDeleted()) { |
| if (Class->hasUserDeclaredDestructor() && !DD->isDefined()) { |
| // If this is an out-of-line declaration, marking it referenced will |
| // not do anything. Manually call CheckDestructor to look up operator |
| // delete(). |
| ContextRAII SavedContext(*this, DD); |
| CheckDestructor(DD); |
| } else { |
| MarkFunctionReferenced(Loc, Class->getDestructor()); |
| } |
| } |
| } |
| } |
| |
| // Local classes need to have their virtual members marked |
| // immediately. For all other classes, we mark their virtual members |
| // at the end of the translation unit. |
| if (Class->isLocalClass()) |
| MarkVirtualMembersReferenced(Loc, Class); |
| else |
| VTableUses.push_back(std::make_pair(Class, Loc)); |
| } |
| |
| bool Sema::DefineUsedVTables() { |
| LoadExternalVTableUses(); |
| if (VTableUses.empty()) |
| return false; |
| |
| // Note: The VTableUses vector could grow as a result of marking |
| // the members of a class as "used", so we check the size each |
| // time through the loop and prefer indices (which are stable) to |
| // iterators (which are not). |
| bool DefinedAnything = false; |
| for (unsigned I = 0; I != VTableUses.size(); ++I) { |
| CXXRecordDecl *Class = VTableUses[I].first->getDefinition(); |
| if (!Class) |
| continue; |
| TemplateSpecializationKind ClassTSK = |
| Class->getTemplateSpecializationKind(); |
| |
| SourceLocation Loc = VTableUses[I].second; |
| |
| bool DefineVTable = true; |
| |
| // If this class has a key function, but that key function is |
| // defined in another translation unit, we don't need to emit the |
| // vtable even though we're using it. |
| const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class); |
| if (KeyFunction && !KeyFunction->hasBody()) { |
| // The key function is in another translation unit. |
| DefineVTable = false; |
| TemplateSpecializationKind TSK = |
| KeyFunction->getTemplateSpecializationKind(); |
| assert(TSK != TSK_ExplicitInstantiationDefinition && |
| TSK != TSK_ImplicitInstantiation && |
| "Instantiations don't have key functions"); |
| (void)TSK; |
| } else if (!KeyFunction) { |
| // If we have a class with no key function that is the subject |
| // of an explicit instantiation declaration, suppress the |
| // vtable; it will live with the explicit instantiation |
| // definition. |
| bool IsExplicitInstantiationDeclaration = |
| ClassTSK == TSK_ExplicitInstantiationDeclaration; |
| for (auto R : Class->redecls()) { |
| TemplateSpecializationKind TSK |
| = cast<CXXRecordDecl>(R)->getTemplateSpecializationKind(); |
| if (TSK == TSK_ExplicitInstantiationDeclaration) |
| IsExplicitInstantiationDeclaration = true; |
| else if (TSK == TSK_ExplicitInstantiationDefinition) { |
| IsExplicitInstantiationDeclaration = false; |
| break; |
| } |
| } |
| |
| if (IsExplicitInstantiationDeclaration) |
| DefineVTable = false; |
| } |
| |
| // The exception specifications for all virtual members may be needed even |
| // if we are not providing an authoritative form of the vtable in this TU. |
| // We may choose to emit it available_externally anyway. |
| if (!DefineVTable) { |
| MarkVirtualMemberExceptionSpecsNeeded(Loc, Class); |
| continue; |
| } |
| |
| // Mark all of the virtual members of this class as referenced, so |
| // that we can build a vtable. Then, tell the AST consumer that a |
| // vtable for this class is required. |
| DefinedAnything = true; |
| MarkVirtualMembersReferenced(Loc, Class); |
| CXXRecordDecl *Canonical = Class->getCanonicalDecl(); |
| if (VTablesUsed[Canonical]) |
| Consumer.HandleVTable(Class); |
| |
| // Warn if we're emitting a weak vtable. The vtable will be weak if there is |
| // no key function or the key function is inlined. Don't warn in C++ ABIs |
| // that lack key functions, since the user won't be able to make one. |
| if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() && |
| Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) { |
| const FunctionDecl *KeyFunctionDef = nullptr; |
| if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) && |
| KeyFunctionDef->isInlined())) { |
| Diag(Class->getLocation(), |
| ClassTSK == TSK_ExplicitInstantiationDefinition |
| ? diag::warn_weak_template_vtable |
| : diag::warn_weak_vtable) |
| << Class; |
| } |
| } |
| } |
| VTableUses.clear(); |
| |
| return DefinedAnything; |
| } |
| |
| void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, |
| const CXXRecordDecl *RD) { |
| for (const auto *I : RD->methods()) |
| if (I->isVirtual() && !I->isPure()) |
| ResolveExceptionSpec(Loc, I->getType()->castAs<FunctionProtoType>()); |
| } |
| |
| void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, |
| const CXXRecordDecl *RD) { |
| // Mark all functions which will appear in RD's vtable as used. |
| CXXFinalOverriderMap FinalOverriders; |
| RD->getFinalOverriders(FinalOverriders); |
| for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(), |
| E = FinalOverriders.end(); |
| I != E; ++I) { |
| for (OverridingMethods::const_iterator OI = I->second.begin(), |
| OE = I->second.end(); |
| OI != OE; ++OI) { |
| assert(OI->second.size() > 0 && "no final overrider"); |
| CXXMethodDecl *Overrider = OI->second.front().Method; |
| |
| // C++ [basic.def.odr]p2: |
| // [...] A virtual member function is used if it is not pure. [...] |
| if (!Overrider->isPure()) |
| MarkFunctionReferenced(Loc, Overrider); |
| } |
| } |
| |
| // Only classes that have virtual bases need a VTT. |
| if (RD->getNumVBases() == 0) |
| return; |
| |
| for (const auto &I : RD->bases()) { |
| const CXXRecordDecl *Base = |
| cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl()); |
| if (Base->getNumVBases() == 0) |
| continue; |
| MarkVirtualMembersReferenced(Loc, Base); |
| } |
| } |
| |
| /// SetIvarInitializers - This routine builds initialization ASTs for the |
| /// Objective-C implementation whose ivars need be initialized. |
| void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { |
| if (!getLangOpts().CPlusPlus) |
| return; |
| if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { |
| SmallVector<ObjCIvarDecl*, 8> ivars; |
| CollectIvarsToConstructOrDestruct(OID, ivars); |
| if (ivars.empty()) |
| return; |
| SmallVector<CXXCtorInitializer*, 32> AllToInit; |
| for (unsigned i = 0; i < ivars.size(); i++) { |
| FieldDecl *Field = ivars[i]; |
| if (Field->isInvalidDecl()) |
| continue; |
| |
| CXXCtorInitializer *Member; |
| InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); |
| InitializationKind InitKind = |
| InitializationKind::CreateDefault(ObjCImplementation->getLocation()); |
| |
| InitializationSequence InitSeq(*this, InitEntity, InitKind, None); |
| ExprResult MemberInit = |
| InitSeq.Perform(*this, InitEntity, InitKind, None); |
| MemberInit = MaybeCreateExprWithCleanups(MemberInit); |
| // Note, MemberInit could actually come back empty if no initialization |
| // is required (e.g., because it would call a trivial default constructor) |
| if (!MemberInit.get() || MemberInit.isInvalid()) |
| continue; |
| |
| Member = |
| new (Context) CXXCtorInitializer(Context, Field, SourceLocation(), |
| SourceLocation(), |
| MemberInit.getAs<Expr>(), |
| SourceLocation()); |
| AllToInit.push_back(Member); |
| |
| // Be sure that the destructor is accessible and is marked as referenced. |
| if (const RecordType *RecordTy = |
| Context.getBaseElementType(Field->getType()) |
| ->getAs<RecordType>()) { |
| CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); |
| if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { |
| MarkFunctionReferenced(Field->getLocation(), Destructor); |
| CheckDestructorAccess(Field->getLocation(), Destructor, |
| PDiag(diag::err_access_dtor_ivar) |
| << Context.getBaseElementType(Field->getType())); |
| } |
| } |
| } |
| ObjCImplementation->setIvarInitializers(Context, |
| AllToInit.data(), AllToInit.size()); |
| } |
| } |
| |
| static |
| void DelegatingCycleHelper(CXXConstructorDecl* Ctor, |
| llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid, |
| llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid, |
| llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current, |
| Sema &S) { |
| if (Ctor->isInvalidDecl()) |
| return; |
| |
| CXXConstructorDecl *Target = Ctor->getTargetConstructor(); |
| |
| // Target may not be determinable yet, for instance if this is a dependent |
| // call in an uninstantiated template. |
| if (Target) { |
| const FunctionDecl *FNTarget = nullptr; |
| (void)Target->hasBody(FNTarget); |
| Target = const_cast<CXXConstructorDecl*>( |
| cast_or_null<CXXConstructorDecl>(FNTarget)); |
| } |
| |
| CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(), |
| // Avoid dereferencing a null pointer here. |
| *TCanonical = Target? Target->getCanonicalDecl() : nullptr; |
| |
| if (!Current.insert(Canonical).second) |
| return; |
| |
| // We know that beyond here, we aren't chaining into a cycle. |
| if (!Target || !Target->isDelegatingConstructor() || |
| Target->isInvalidDecl() || Valid.count(TCanonical)) { |
| Valid.insert(Current.begin(), Current.end()); |
| Current.clear(); |
| // We've hit a cycle. |
| } else if (TCanonical == Canonical || Invalid.count(TCanonical) || |
| Current.count(TCanonical)) { |
| // If we haven't diagnosed this cycle yet, do so now. |
| if (!Invalid.count(TCanonical)) { |
| S.Diag((*Ctor->init_begin())->getSourceLocation(), |
| diag::warn_delegating_ctor_cycle) |
| << Ctor; |
| |
| // Don't add a note for a function delegating directly to itself. |
| if (TCanonical != Canonical) |
| S.Diag(Target->getLocation(), diag::note_it_delegates_to); |
| |
| CXXConstructorDecl *C = Target; |
| while (C->getCanonicalDecl() != Canonical) { |
| const FunctionDecl *FNTarget = nullptr; |
| (void)C->getTargetConstructor()->hasBody(FNTarget); |
| assert(FNTarget && "Ctor cycle through bodiless function"); |
| |
| C = const_cast<CXXConstructorDecl*>( |
| cast<CXXConstructorDecl>(FNTarget)); |
| S.Diag(C->getLocation(), diag::note_which_delegates_to); |
| } |
| } |
| |
| Invalid.insert(Current.begin(), Current.end()); |
| Current.clear(); |
| } else { |
| DelegatingCycleHelper(Target, Valid, Invalid, Current, S); |
| } |
| } |
| |
| |
| void Sema::CheckDelegatingCtorCycles() { |
| llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current; |
| |
| for (DelegatingCtorDeclsType::iterator |
| I = DelegatingCtorDecls.begin(ExternalSource), |
| E = DelegatingCtorDecls.end(); |
| I != E; ++I) |
| DelegatingCycleHelper(*I, Valid, Invalid, Current, *this); |
| |
| for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI) |
| (*CI)->setInvalidDecl(); |
| } |
| |
| namespace { |
| /// AST visitor that finds references to the 'this' expression. |
| class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> { |
| Sema &S; |
| |
| public: |
| explicit FindCXXThisExpr(Sema &S) : S(S) { } |
| |
| bool VisitCXXThisExpr(CXXThisExpr *E) { |
| S.Diag(E->getLocation(), diag::err_this_static_member_func) |
| << E->isImplicit(); |
| return false; |
| } |
| }; |
| } |
| |
| bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) { |
| TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); |
| if (!TSInfo) |
| return false; |
| |
| TypeLoc TL = TSInfo->getTypeLoc(); |
| FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); |
| if (!ProtoTL) |
| return false; |
| |
| // C++11 [expr.prim.general]p3: |
| // [The expression this] shall not appear before the optional |
| // cv-qualifier-seq and it shall not appear within the declaration of a |
| // static member function (although its type and value category are defined |
| // within a static member function as they are within a non-static member |
| // function). [ Note: this is because declaration matching does not occur |
| // until the complete declarator is known. - end note ] |
| const FunctionProtoType *Proto = ProtoTL.getTypePtr(); |
| FindCXXThisExpr Finder(*this); |
| |
| // If the return type came after the cv-qualifier-seq, check it now. |
| if (Proto->hasTrailingReturn() && |
| !Finder.TraverseTypeLoc(ProtoTL.getReturnLoc())) |
| return true; |
| |
| // Check the exception specification. |
| if (checkThisInStaticMemberFunctionExceptionSpec(Method)) |
| return true; |
| |
| return checkThisInStaticMemberFunctionAttributes(Method); |
| } |
| |
| bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) { |
| TypeSourceInfo *TSInfo = Method->getTypeSourceInfo(); |
| if (!TSInfo) |
| return false; |
| |
| TypeLoc TL = TSInfo->getTypeLoc(); |
| FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>(); |
| if (!ProtoTL) |
| return false; |
| |
| const FunctionProtoType *Proto = ProtoTL.getTypePtr(); |
| FindCXXThisExpr Finder(*this); |
| |
| switch (Proto->getExceptionSpecType()) { |
| case EST_Unparsed: |
| case EST_Uninstantiated: |
| case EST_Unevaluated: |
| case EST_BasicNoexcept: |
| case EST_DynamicNone: |
| case EST_MSAny: |
| case EST_None: |
| break; |
| |
| case EST_DependentNoexcept: |
| case EST_NoexceptFalse: |
| case EST_NoexceptTrue: |
| if (!Finder.TraverseStmt(Proto->getNoexceptExpr())) |
| return true; |
| LLVM_FALLTHROUGH; |
| |
| case EST_Dynamic: |
| for (const auto &E : Proto->exceptions()) { |
| if (!Finder.TraverseType(E)) |
| return true; |
| } |
| break; |
| } |
| |
| return false; |
| } |
| |
| bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) { |
| FindCXXThisExpr Finder(*this); |
| |
| // Check attributes. |
| for (const auto *A : Method->attrs()) { |
| // FIXME: This should be emitted by tblgen. |
| Expr *Arg = nullptr; |
| ArrayRef<Expr *> Args; |
| if (const auto *G = dyn_cast<GuardedByAttr>(A)) |
| Arg = G->getArg(); |
| else if (const auto *G = dyn_cast<PtGuardedByAttr>(A)) |
| Arg = G->getArg(); |
| else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A)) |
| Args = llvm::makeArrayRef(AA->args_begin(), AA->args_size()); |
| else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A)) |
| Args = llvm::makeArrayRef(AB->args_begin(), AB->args_size()); |
| else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) { |
| Arg = ETLF->getSuccessValue(); |
| Args = llvm::makeArrayRef(ETLF->args_begin(), ETLF->args_size()); |
| } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) { |
| Arg = STLF->getSuccessValue(); |
| Args = llvm::makeArrayRef(STLF->args_begin(), STLF->args_size()); |
| } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A)) |
| Arg = LR->getArg(); |
| else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A)) |
| Args = llvm::makeArrayRef(LE->args_begin(), LE->args_size()); |
| else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A)) |
| Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size()); |
| else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A)) |
| Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size()); |
| else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A)) |
| Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size()); |
| else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A)) |
| Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size()); |
| |
| if (Arg && !Finder.TraverseStmt(Arg)) |
| return true; |
| |
| for (unsigned I = 0, N = Args.size(); I != N; ++I) { |
| if (!Finder.TraverseStmt(Args[I])) |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| void Sema::checkExceptionSpecification( |
| bool IsTopLevel, ExceptionSpecificationType EST, |
| ArrayRef<ParsedType> DynamicExceptions, |
| ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, |
| SmallVectorImpl<QualType> &Exceptions, |
| FunctionProtoType::ExceptionSpecInfo &ESI) { |
| Exceptions.clear(); |
| ESI.Type = EST; |
| if (EST == EST_Dynamic) { |
| Exceptions.reserve(DynamicExceptions.size()); |
| for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) { |
| // FIXME: Preserve type source info. |
| QualType ET = GetTypeFromParser(DynamicExceptions[ei]); |
| |
| if (IsTopLevel) { |
| SmallVector<UnexpandedParameterPack, 2> Unexpanded; |
| collectUnexpandedParameterPacks(ET, Unexpanded); |
| if (!Unexpanded.empty()) { |
| DiagnoseUnexpandedParameterPacks( |
| DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType, |
| Unexpanded); |
| continue; |
| } |
| } |
| |
| // Check that the type is valid for an exception spec, and |
| // drop it if not. |
| if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei])) |
| Exceptions.push_back(ET); |
| } |
| ESI.Exceptions = Exceptions; |
| return; |
| } |
| |
| if (isComputedNoexcept(EST)) { |
| assert((NoexceptExpr->isTypeDependent() || |
| NoexceptExpr->getType()->getCanonicalTypeUnqualified() == |
| Context.BoolTy) && |
| "Parser should have made sure that the expression is boolean"); |
| if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) { |
| ESI.Type = EST_BasicNoexcept; |
| return; |
| } |
| |
| ESI.NoexceptExpr = NoexceptExpr; |
| return; |
| } |
| } |
| |
| void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, |
| ExceptionSpecificationType EST, |
| SourceRange SpecificationRange, |
| ArrayRef<ParsedType> DynamicExceptions, |
| ArrayRef<SourceRange> DynamicExceptionRanges, |
| Expr *NoexceptExpr) { |
| if (!MethodD) |
| return; |
| |
| // Dig out the method we're referring to. |
| if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD)) |
| MethodD = FunTmpl->getTemplatedDecl(); |
| |
| CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD); |
| if (!Method) |
| return; |
| |
| // Check the exception specification. |
| llvm::SmallVector<QualType, 4> Exceptions; |
| FunctionProtoType::ExceptionSpecInfo ESI; |
| checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions, |
| DynamicExceptionRanges, NoexceptExpr, Exceptions, |
| ESI); |
| |
| // Update the exception specification on the function type. |
| Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true); |
| |
| if (Method->isStatic()) |
| checkThisInStaticMemberFunctionExceptionSpec(Method); |
| |
| if (Method->isVirtual()) { |
| // Check overrides, which we previously had to delay. |
| for (const CXXMethodDecl *O : Method->overridden_methods()) |
| CheckOverridingFunctionExceptionSpec(Method, O); |
| } |
| } |
| |
| /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. |
| /// |
| MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, |
| SourceLocation DeclStart, Declarator &D, |
| Expr *BitWidth, |
| InClassInitStyle InitStyle, |
| AccessSpecifier AS, |
| const ParsedAttr &MSPropertyAttr) { |
| IdentifierInfo *II = D.getIdentifier(); |
| if (!II) { |
| Diag(DeclStart, diag::err_anonymous_property); |
| return nullptr; |
| } |
| SourceLocation Loc = D.getIdentifierLoc(); |
| |
| TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); |
| QualType T = TInfo->getType(); |
| if (getLangOpts().CPlusPlus) { |
| CheckExtraCXXDefaultArguments(D); |
| |
| if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo, |
| UPPC_DataMemberType)) { |
| D.setInvalidType(); |
| T = Context.IntTy; |
| TInfo = Context.getTrivialTypeSourceInfo(T, Loc); |
| } |
| } |
| |
| DiagnoseFunctionSpecifiers(D.getDeclSpec()); |
| |
| if (D.getDeclSpec().isInlineSpecified()) |
| Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) |
| << getLangOpts().CPlusPlus17; |
| if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) |
| Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), |
| diag::err_invalid_thread) |
| << DeclSpec::getSpecifierName(TSCS); |
| |
| // Check to see if this name was declared as a member previously |
| NamedDecl *PrevDecl = nullptr; |
| LookupResult Previous(*this, II, Loc, LookupMemberName, |
| ForVisibleRedeclaration); |
| LookupName(Previous, S); |
| switch (Previous.getResultKind()) { |
| case LookupResult::Found: |
| case LookupResult::FoundUnresolvedValue: |
| PrevDecl = Previous.getAsSingle<NamedDecl>(); |
| break; |
| |
| case LookupResult::FoundOverloaded: |
| PrevDecl = Previous.getRepresentativeDecl(); |
| break; |
| |
| case LookupResult::NotFound: |
| case LookupResult::NotFoundInCurrentInstantiation: |
| case LookupResult::Ambiguous: |
| break; |
| } |
| |
| if (PrevDecl && PrevDecl->isTemplateParameter()) { |
| // Maybe we will complain about the shadowed template parameter. |
| DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); |
| // Just pretend that we didn't see the previous declaration. |
| PrevDecl = nullptr; |
| } |
| |
| if (PrevDecl && !isDeclInScope(PrevDecl, Record, S)) |
| PrevDecl = nullptr; |
| |
| SourceLocation TSSL = D.getLocStart(); |
| const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData(); |
| MSPropertyDecl *NewPD = MSPropertyDecl::Create( |
| Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); |
| ProcessDeclAttributes(TUScope, NewPD, D); |
| NewPD->setAccess(AS); |
| |
| if (NewPD->isInvalidDecl()) |
| Record->setInvalidDecl(); |
| |
| if (D.getDeclSpec().isModulePrivateSpecified()) |
| NewPD->setModulePrivate(); |
| |
| if (NewPD->isInvalidDecl() && PrevDecl) { |
| // Don't introduce NewFD into scope; there's already something |
| // with the same name in the same scope. |
| } else if (II) { |
| PushOnScopeChains(NewPD, S); |
| } else |
| Record->addDecl(NewPD); |
| |
| return NewPD; |
| } |