| //===------ 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/Sema/SemaInternal.h" |
| #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/DeclVisitor.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 "llvm/ADT/STLExtras.h" |
| #include "llvm/ADT/SmallString.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::child_range I = Node->children(); I; ++I) |
| IsInvalid |= Visit(*I); |
| 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 this function can throw any exceptions, make a note of that. |
| if (EST == EST_MSAny || EST == EST_None) { |
| ClearExceptions(); |
| ComputedEST = EST; |
| return; |
| } |
| |
| // FIXME: If the call to this decl is using any of its default arguments, we |
| // need to search them for potentially-throwing calls. |
| |
| // If this function has a basic noexcept, it doesn't affect the outcome. |
| if (EST == EST_BasicNoexcept) |
| return; |
| |
| // If we have a throw-all spec at this point, ignore the function. |
| if (ComputedEST == EST_None) |
| return; |
| |
| // If we're still at noexcept(true) and there's a nothrow() callee, |
| // change to that specification. |
| if (EST == EST_DynamicNone) { |
| if (ComputedEST == EST_BasicNoexcept) |
| ComputedEST = EST_DynamicNone; |
| return; |
| } |
| |
| // Check out noexcept specs. |
| if (EST == EST_ComputedNoexcept) { |
| FunctionProtoType::NoexceptResult NR = |
| Proto->getNoexceptSpec(Self->Context); |
| assert(NR != FunctionProtoType::NR_NoNoexcept && |
| "Must have noexcept result for EST_ComputedNoexcept."); |
| assert(NR != FunctionProtoType::NR_Dependent && |
| "Should not generate implicit declarations for dependent cases, " |
| "and don't know how to handle them anyway."); |
| |
| // noexcept(false) -> no spec on the new function |
| if (NR == FunctionProtoType::NR_Throw) { |
| ClearExceptions(); |
| ComputedEST = EST_None; |
| } |
| // noexcept(true) won't change anything either. |
| return; |
| } |
| |
| 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))) |
| 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.takeAs<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; |
| } |
| |
| // 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) { |
| if (!param) |
| return; |
| |
| ParmVarDecl *Param = cast<ParmVarDecl>(param); |
| Param->setInvalidDecl(); |
| UnparsedDefaultArgLocs.erase(Param); |
| } |
| |
| /// 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()) { |
| CachedTokens *Toks = chunk.Fun.Params[argIdx].DefaultArgTokens; |
| Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) |
| << SourceRange((*Toks)[1].getLocation(), |
| Toks->back().getLocation()); |
| delete Toks; |
| chunk.Fun.Params[argIdx].DefaultArgTokens = 0; |
| } else if (Param->getDefaultArg()) { |
| Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc) |
| << Param->getDefaultArg()->getSourceRange(); |
| Param->setDefaultArg(0); |
| } |
| } |
| } 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; |
| |
| // 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 = Old->getNumParams(); p < NumParams; ++p) { |
| ParmVarDecl *OldParam = Old->getParamDecl(p); |
| ParmVarDecl *NewParam = New->getParamDecl(p); |
| |
| bool OldParamHasDfl = OldParam->hasDefaultArg(); |
| bool NewParamHasDfl = NewParam->hasDefaultArg(); |
| |
| NamedDecl *ND = Old; |
| |
| // 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->getLexicalDeclContext(); |
| if (!ScopeDC->isFunctionOrMethod()) |
| ScopeDC = New->getDeclContext(); |
| if (S && !isDeclInScope(ND, ScopeDC, S) && |
| !New->getDeclContext()->isRecord()) |
| // Ignore default parameters of old decl if they are not in |
| // the same scope and this is not an out-of-line definition of |
| // a member function. |
| OldParamHasDfl = false; |
| |
| 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::warn_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 (FunctionDecl *Older = Old->getPreviousDecl(); |
| Older; Older = Older->getPreviousDecl()) { |
| if (!Older->getParamDecl(p)->hasDefaultArg()) |
| break; |
| |
| 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. |
| // It's important to use getInit() here; getDefaultArg() |
| // strips off any top-level ExprWithCleanups. |
| NewParam->setHasInheritedDefaultArg(); |
| 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(Old->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->isInlined() && New->isInlined() && Old->isDefined(Def)) { |
| // C++11 [dcl.fcn.spec]p4: |
| // If the definition of a function appears in a translation unit before its |
| // first declaration as inline, the program is ill-formed. |
| Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New; |
| Diag(Def->getLocation(), diag::note_previous_definition); |
| Invalid = true; |
| } |
| |
| // C++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; |
| } |
| |
| if (CheckEquivalentExceptionSpec(Old, New)) |
| Invalid = true; |
| |
| return Invalid; |
| } |
| |
| /// \brief 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++ [dcl.fct.default]p4: |
| // 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). |
| unsigned LastMissingDefaultArg = 0; |
| for (; p < NumParams; ++p) { |
| ParmVarDecl *Param = FD->getParamDecl(p); |
| if (!Param->hasDefaultArg()) { |
| 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(0); |
| } |
| } |
| } |
| } |
| |
| // 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; |
| } |
| |
| /// \brief 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()) { |
| Diag(NewFD->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().CPlusPlus1y |
| ? 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: { |
| // 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().CPlusPlus1y |
| ? 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().CPlusPlus1y) |
| break; |
| if (!Cxx1yLoc.isValid()) |
| Cxx1yLoc = S->getLocStart(); |
| for (Stmt::child_range Children = S->children(); Children; ++Children) |
| if (*Children && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, 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::child_range Children = S->children(); Children; ++Children) |
| if (*Children && |
| !CheckConstexprFunctionStmt(SemaRef, Dcl, *Children, 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().CPlusPlus1y |
| ? 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().CPlusPlus1y && |
| (Dcl->getReturnType()->isVoidType() || |
| Dcl->getReturnType()->isDependentType()); |
| Diag(Dcl->getLocation(), |
| OK ? diag::warn_cxx11_compat_constexpr_body_no_return |
| : diag::err_constexpr_body_no_return); |
| return OK; |
| } |
| if (ReturnStmts.size() > 1) { |
| Diag(ReturnStmts.back(), |
| getLangOpts().CPlusPlus1y |
| ? 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; |
| } |
| |
| /// 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 *, |
| const CXXScopeSpec *SS) { |
| assert(getLangOpts().CPlusPlus && "No class names in C!"); |
| |
| 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()) |
| return &II == CurDecl->getIdentifier(); |
| return false; |
| } |
| |
| /// \brief 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; |
| } |
| |
| /// \brief 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; |
| } |
| |
| /// \brief 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 0; |
| } |
| |
| 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 0; |
| } |
| } |
| |
| 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 0; |
| } |
| |
| // 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 0; |
| } |
| |
| // 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 0; |
| } |
| |
| // 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"); |
| |
| // 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 0; |
| } |
| |
| // 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_previous_decl) |
| << CXXBaseDecl->getDeclName(); |
| return 0; |
| } |
| |
| 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 do not support any C++11 attributes on base-specifiers yet. |
| // Diagnose any attributes we see. |
| if (!Attributes.empty()) { |
| for (AttributeList *Attr = Attributes.getList(); Attr; |
| Attr = Attr->getNext()) { |
| if (Attr->isInvalid() || |
| Attr->getKind() == AttributeList::IgnoredAttribute) |
| continue; |
| Diag(Attr->getLoc(), |
| Attr->getKind() == AttributeList::UnknownAttribute |
| ? diag::warn_unknown_attribute_ignored |
| : diag::err_base_specifier_attribute) |
| << Attr->getName(); |
| } |
| } |
| |
| TypeSourceInfo *TInfo = 0; |
| 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; |
| } |
| |
| /// \brief Performs the actual work of attaching the given base class |
| /// specifiers to a C++ class. |
| bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, |
| unsigned NumBases) { |
| if (NumBases == 0) |
| 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; |
| |
| // Copy non-redundant base specifiers into permanent storage. |
| unsigned NumGoodBases = 0; |
| bool Invalid = false; |
| for (unsigned idx = 0; idx < NumBases; ++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]; |
| if (const RecordType *Record = NewBaseType->getAs<RecordType>()) { |
| const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); |
| if (Class->isInterface() && |
| (!RD->isInterface() || |
| 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->getName() |
| << 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, NumGoodBases); |
| |
| // Delete the remaining (good) base class specifiers, since their |
| // data has been copied into the CXXRecordDecl. |
| for (unsigned idx = 0; idx < NumGoodBases; ++idx) |
| 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, CXXBaseSpecifier **Bases, |
| unsigned NumBases) { |
| if (!ClassDecl || !Bases || !NumBases) |
| return; |
| |
| AdjustDeclIfTemplate(ClassDecl); |
| AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases, NumBases); |
| } |
| |
| /// \brief Determine whether the type \p Derived is a C++ class that is |
| /// derived from the type \p Base. |
| bool Sema::IsDerivedFrom(QualType Derived, QualType Base) { |
| 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: instantiate DerivedRD if necessary. We need a PoI for this. |
| return DerivedRD->hasDefinition() && DerivedRD->isDerivedFrom(BaseRD); |
| } |
| |
| /// \brief Determine whether the type \p Derived is a C++ class that is |
| /// derived from the type \p Base. |
| bool Sema::IsDerivedFrom(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; |
| |
| return DerivedRD->isDerivedFrom(BaseRD, Paths); |
| } |
| |
| void Sema::BuildBasePathArray(const CXXBasePaths &Paths, |
| CXXCastPath &BasePathArray) { |
| assert(BasePathArray.empty() && "Base path array must be empty!"); |
| assert(Paths.isRecordingPaths() && "Must record paths!"); |
| |
| const CXXBasePath &Path = Paths.front(); |
| |
| // 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)); |
| } |
| |
| /// \brief Determine whether the given base path includes a virtual |
| /// base class. |
| bool Sema::BasePathInvolvesVirtualBase(const CXXCastPath &BasePath) { |
| for (CXXCastPath::const_iterator B = BasePath.begin(), |
| BEnd = BasePath.end(); |
| B != BEnd; ++B) |
| if ((*B)->isVirtual()) |
| return true; |
| |
| return false; |
| } |
| |
| /// 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. |
| bool |
| Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base, |
| unsigned InaccessibleBaseID, |
| unsigned AmbigiousBaseConvID, |
| SourceLocation Loc, SourceRange Range, |
| DeclarationName Name, |
| CXXCastPath *BasePath) { |
| // 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(Derived, Base, Paths); |
| assert(DerivationOkay && |
| "Can only be used with a derived-to-base conversion"); |
| (void)DerivationOkay; |
| |
| if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) { |
| if (InaccessibleBaseID) { |
| // Check that the base class can be accessed. |
| switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(), |
| 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(Paths, *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(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, |
| IgnoreAccess ? 0 |
| : diag::err_upcast_to_inaccessible_base, |
| diag::err_ambiguous_derived_to_base_conv, |
| Loc, Range, DeclarationName(), |
| BasePath); |
| } |
| |
| |
| /// @brief 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, |
| AttributeList *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 virtual 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->begin_overridden_methods() != MD->end_overridden_methods(); |
| if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) |
| Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding) |
| << MD->getDeclName(); |
| } |
| |
| /// 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 AttributeList *getMSPropertyAttr(AttributeList *list) { |
| for (AttributeList* it = list; it != 0; it = it->getNext()) |
| if (it->isDeclspecPropertyAttribute()) |
| return it; |
| return 0; |
| } |
| |
| /// 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(); |
| |
| 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) |
| InvalidDecl = (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) ? 0 : 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 0; |
| } |
| } |
| |
| // 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 0; |
| } |
| |
| 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 0; |
| } |
| |
| 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()); |
| else |
| Diag(D.getIdentifierLoc(), diag::err_member_qualification) |
| << Name << SS.getRange(); |
| |
| SS.clear(); |
| } |
| |
| AttributeList *MSPropertyAttr = |
| getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); |
| if (MSPropertyAttr) { |
| Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D, |
| BitWidth, InitStyle, AS, MSPropertyAttr); |
| if (!Member) |
| return 0; |
| isInstField = false; |
| } else { |
| Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D, |
| BitWidth, InitStyle, AS); |
| assert(Member && "HandleField never returns null"); |
| } |
| } else { |
| assert(InitStyle == ICIS_NoInit || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static); |
| |
| Member = HandleDeclarator(S, D, TemplateParameterLists); |
| if (!Member) |
| return 0; |
| |
| // Non-instance-fields can't have a bitfield. |
| if (BitWidth) { |
| if (Member->isInvalidDecl()) { |
| // don't emit another diagnostic. |
| } else if (isa<VarDecl>(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 = 0; |
| Member->setInvalidDecl(); |
| } |
| |
| 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 (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member)) |
| FunTmpl->getTemplatedDecl()->setAccess(AS); |
| else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member)) |
| VarTmpl->getTemplatedDecl()->setAccess(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.getDiagnosticLevel(diag::warn_unused_private_field, |
| FD->getLocation()) |
| != DiagnosticsEngine::Ignored) { |
| // 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::SmallPtrSet<ValueDecl*, 4> &Decls; |
| // If non-null, add a note to the warning pointing back to the constructor. |
| const CXXConstructorDecl *Constructor; |
| public: |
| typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited; |
| UninitializedFieldVisitor(Sema &S, |
| llvm::SmallPtrSet<ValueDecl*, 4> &Decls, |
| const CXXConstructorDecl *Constructor) |
| : Inherited(S.Context), S(S), Decls(Decls), |
| Constructor(Constructor) { } |
| |
| void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly) { |
| if (isa<EnumConstantDecl>(ME->getMemberDecl())) |
| return; |
| |
| // FieldME is the inner-most MemberExpr that is not an anonymous struct |
| // or union. |
| MemberExpr *FieldME = ME; |
| |
| Expr *Base = ME; |
| while (isa<MemberExpr>(Base)) { |
| ME = cast<MemberExpr>(Base); |
| |
| if (isa<VarDecl>(ME->getMemberDecl())) |
| return; |
| |
| if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) |
| if (!FD->isAnonymousStructOrUnion()) |
| FieldME = ME; |
| |
| Base = ME->getBase(); |
| } |
| |
| if (!isa<CXXThisExpr>(Base)) |
| return; |
| |
| ValueDecl* FoundVD = FieldME->getMemberDecl(); |
| |
| if (!Decls.count(FoundVD)) |
| return; |
| |
| const bool IsReference = FoundVD->getType()->isReferenceType(); |
| |
| // Prevent double warnings on use of unbounded references. |
| if (IsReference != CheckReferenceOnly) |
| 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) { |
| E = E->IgnoreParens(); |
| |
| if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) { |
| HandleMemberExpr(ME, false /*CheckReferenceOnly*/); |
| return; |
| } |
| |
| if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) { |
| HandleValue(CO->getTrueExpr()); |
| HandleValue(CO->getFalseExpr()); |
| return; |
| } |
| |
| if (BinaryConditionalOperator *BCO = |
| dyn_cast<BinaryConditionalOperator>(E)) { |
| HandleValue(BCO->getCommon()); |
| HandleValue(BCO->getFalseExpr()); |
| return; |
| } |
| |
| if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) { |
| switch (BO->getOpcode()) { |
| default: |
| return; |
| case(BO_PtrMemD): |
| case(BO_PtrMemI): |
| HandleValue(BO->getLHS()); |
| return; |
| case(BO_Comma): |
| HandleValue(BO->getRHS()); |
| return; |
| } |
| } |
| } |
| |
| void VisitMemberExpr(MemberExpr *ME) { |
| // All uses of unbounded reference fields will warn. |
| HandleMemberExpr(ME, true /*CheckReferenceOnly*/); |
| |
| Inherited::VisitMemberExpr(ME); |
| } |
| |
| void VisitImplicitCastExpr(ImplicitCastExpr *E) { |
| if (E->getCastKind() == CK_LValueToRValue) |
| HandleValue(E->getSubExpr()); |
| |
| Inherited::VisitImplicitCastExpr(E); |
| } |
| |
| void VisitCXXConstructExpr(CXXConstructExpr *E) { |
| if (E->getConstructor()->isCopyConstructor()) |
| if (ImplicitCastExpr* ICE = dyn_cast<ImplicitCastExpr>(E->getArg(0))) |
| if (ICE->getCastKind() == CK_NoOp) |
| if (MemberExpr *ME = dyn_cast<MemberExpr>(ICE->getSubExpr())) |
| HandleMemberExpr(ME, false /*CheckReferenceOnly*/); |
| |
| Inherited::VisitCXXConstructExpr(E); |
| } |
| |
| void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) { |
| Expr *Callee = E->getCallee(); |
| if (isa<MemberExpr>(Callee)) |
| HandleValue(Callee); |
| |
| Inherited::VisitCXXMemberCallExpr(E); |
| } |
| |
| 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()) |
| Decls.erase(FD); |
| |
| Inherited::VisitBinaryOperator(E); |
| } |
| }; |
| static void CheckInitExprContainsUninitializedFields( |
| Sema &S, Expr *E, llvm::SmallPtrSet<ValueDecl*, 4> &Decls, |
| const CXXConstructorDecl *Constructor) { |
| if (Decls.size() == 0) |
| return; |
| |
| if (!E) |
| return; |
| |
| if (CXXDefaultInitExpr *Default = dyn_cast<CXXDefaultInitExpr>(E)) { |
| E = Default->getExpr(); |
| if (!E) |
| return; |
| // In class initializers will point to the constructor. |
| UninitializedFieldVisitor(S, Decls, Constructor).Visit(E); |
| } else { |
| UninitializedFieldVisitor(S, Decls, 0).Visit(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().getDiagnosticLevel(diag::warn_field_is_uninit, |
| Constructor->getLocation()) |
| == DiagnosticsEngine::Ignored) { |
| return; |
| } |
| |
| if (Constructor->isInvalidDecl()) |
| return; |
| |
| const CXXRecordDecl *RD = Constructor->getParent(); |
| |
| // 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()); |
| } |
| } |
| |
| for (const auto *FieldInit : Constructor->inits()) { |
| Expr *InitExpr = FieldInit->getInit(); |
| |
| CheckInitExprContainsUninitializedFields( |
| SemaRef, InitExpr, UninitializedFields, Constructor); |
| |
| if (FieldDecl *Field = FieldInit->getAnyMember()) |
| UninitializedFields.erase(Field); |
| } |
| } |
| } // namespace |
| |
| /// \brief 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(); |
| } |
| |
| /// \brief 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(0, D); |
| |
| FieldDecl *FD = cast<FieldDecl>(D); |
| assert(FD->getInClassInitStyle() != ICIS_NoInit && |
| "must set init style when field is created"); |
| |
| if (!InitExpr) { |
| FD->setInvalidDecl(); |
| 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::InitializeMember(FD); |
| InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit |
| ? InitializationKind::CreateDirectList(InitExpr->getLocStart()) |
| : 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.take(), InitLoc); |
| if (Init.isInvalid()) { |
| FD->setInvalidDecl(); |
| return; |
| } |
| |
| InitExpr = Init.release(); |
| |
| FD->setInClassInitializer(InitExpr); |
| } |
| |
| /// \brief 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 = 0; |
| 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 = 0; |
| 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(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; |
| } |
| |
| /// \brief 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); |
| } |
| |
| /// \brief 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; |
| }; |
| |
| } |
| |
| /// \brief 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) { |
| 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 = 0; |
| |
| if (TemplateTypeTy) { |
| BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo); |
| } else if (DS.getTypeSpecType() == TST_decltype) { |
| BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); |
| } 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; |
| |
| R.clear(); |
| R.setLookupName(MemberOrBase); |
| } |
| } |
| |
| // If no results were found, try to correct typos. |
| TypoCorrection Corr; |
| MemInitializerValidatorCCC Validator(ClassDecl); |
| if (R.empty() && BaseType.isNull() && |
| (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, |
| Validator, 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); |
| if (SS.isSet()) |
| // FIXME: preserve source range information |
| BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(), |
| BaseType); |
| } |
| } |
| |
| if (!TInfo) |
| TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); |
| |
| return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); |
| } |
| |
| /// Checks a member initializer expression for cases where reference (or |
| /// pointer) members are bound to by-value parameters (or their addresses). |
| static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member, |
| Expr *Init, |
| SourceLocation IdLoc) { |
| QualType MemberTy = Member->getType(); |
| |
| // We only handle pointers and references currently. |
| // FIXME: Would this be relevant for ObjC object pointers? Or block pointers? |
| if (!MemberTy->isReferenceType() && !MemberTy->isPointerType()) |
| return; |
| |
| const bool IsPointer = MemberTy->isPointerType(); |
| if (IsPointer) { |
| if (const UnaryOperator *Op |
| = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) { |
| // The only case we're worried about with pointers requires taking the |
| // address. |
| if (Op->getOpcode() != UO_AddrOf) |
| return; |
| |
| Init = Op->getSubExpr(); |
| } else { |
| // We only handle address-of expression initializers for pointers. |
| return; |
| } |
| } |
| |
| if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) { |
| // We only warn when referring to a non-reference parameter declaration. |
| const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl()); |
| if (!Parameter || Parameter->getType()->isReferenceType()) |
| return; |
| |
| S.Diag(Init->getExprLoc(), |
| IsPointer ? diag::warn_init_ptr_member_to_parameter_addr |
| : diag::warn_bind_ref_member_to_parameter) |
| << Member << Parameter << Init->getSourceRange(); |
| } else { |
| // Other initializers are fine. |
| return; |
| } |
| |
| S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here) |
| << (unsigned)IsPointer; |
| } |
| |
| 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, 0) |
| : InitializedEntity::InitializeMember(IndirectMember, 0); |
| InitializationKind Kind = |
| InitList ? InitializationKind::CreateDirectList(IdLoc) |
| : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), |
| InitRange.getEnd()); |
| |
| InitializationSequence InitSeq(*this, MemberEntity, Kind, Args); |
| ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args, 0); |
| if (MemberInit.isInvalid()) |
| return true; |
| |
| CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc); |
| |
| // 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 |