| //===--- SemaExprCXX.cpp - Semantic Analysis for Expressions --------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// Implements semantic analysis for C++ expressions. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #include "clang/Sema/SemaInternal.h" |
| #include "TreeTransform.h" |
| #include "TypeLocBuilder.h" |
| #include "clang/AST/ASTContext.h" |
| #include "clang/AST/ASTLambda.h" |
| #include "clang/AST/CXXInheritance.h" |
| #include "clang/AST/CharUnits.h" |
| #include "clang/AST/DeclObjC.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| #include "clang/AST/RecursiveASTVisitor.h" |
| #include "clang/AST/TypeLoc.h" |
| #include "clang/Basic/AlignedAllocation.h" |
| #include "clang/Basic/PartialDiagnostic.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/Lex/Preprocessor.h" |
| #include "clang/Sema/DeclSpec.h" |
| #include "clang/Sema/Initialization.h" |
| #include "clang/Sema/Lookup.h" |
| #include "clang/Sema/ParsedTemplate.h" |
| #include "clang/Sema/Scope.h" |
| #include "clang/Sema/ScopeInfo.h" |
| #include "clang/Sema/SemaLambda.h" |
| #include "clang/Sema/TemplateDeduction.h" |
| #include "llvm/ADT/APInt.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/Support/ErrorHandling.h" |
| using namespace clang; |
| using namespace sema; |
| |
| /// Handle the result of the special case name lookup for inheriting |
| /// constructor declarations. 'NS::X::X' and 'NS::X<...>::X' are treated as |
| /// constructor names in member using declarations, even if 'X' is not the |
| /// name of the corresponding type. |
| ParsedType Sema::getInheritingConstructorName(CXXScopeSpec &SS, |
| SourceLocation NameLoc, |
| IdentifierInfo &Name) { |
| NestedNameSpecifier *NNS = SS.getScopeRep(); |
| |
| // Convert the nested-name-specifier into a type. |
| QualType Type; |
| switch (NNS->getKind()) { |
| case NestedNameSpecifier::TypeSpec: |
| case NestedNameSpecifier::TypeSpecWithTemplate: |
| Type = QualType(NNS->getAsType(), 0); |
| break; |
| |
| case NestedNameSpecifier::Identifier: |
| // Strip off the last layer of the nested-name-specifier and build a |
| // typename type for it. |
| assert(NNS->getAsIdentifier() == &Name && "not a constructor name"); |
| Type = Context.getDependentNameType(ETK_None, NNS->getPrefix(), |
| NNS->getAsIdentifier()); |
| break; |
| |
| case NestedNameSpecifier::Global: |
| case NestedNameSpecifier::Super: |
| case NestedNameSpecifier::Namespace: |
| case NestedNameSpecifier::NamespaceAlias: |
| llvm_unreachable("Nested name specifier is not a type for inheriting ctor"); |
| } |
| |
| // This reference to the type is located entirely at the location of the |
| // final identifier in the qualified-id. |
| return CreateParsedType(Type, |
| Context.getTrivialTypeSourceInfo(Type, NameLoc)); |
| } |
| |
| ParsedType Sema::getConstructorName(IdentifierInfo &II, |
| SourceLocation NameLoc, |
| Scope *S, CXXScopeSpec &SS, |
| bool EnteringContext) { |
| CXXRecordDecl *CurClass = getCurrentClass(S, &SS); |
| assert(CurClass && &II == CurClass->getIdentifier() && |
| "not a constructor name"); |
| |
| // When naming a constructor as a member of a dependent context (eg, in a |
| // friend declaration or an inherited constructor declaration), form an |
| // unresolved "typename" type. |
| if (CurClass->isDependentContext() && !EnteringContext && SS.getScopeRep()) { |
| QualType T = Context.getDependentNameType(ETK_None, SS.getScopeRep(), &II); |
| return ParsedType::make(T); |
| } |
| |
| if (SS.isNotEmpty() && RequireCompleteDeclContext(SS, CurClass)) |
| return ParsedType(); |
| |
| // Find the injected-class-name declaration. Note that we make no attempt to |
| // diagnose cases where the injected-class-name is shadowed: the only |
| // declaration that can validly shadow the injected-class-name is a |
| // non-static data member, and if the class contains both a non-static data |
| // member and a constructor then it is ill-formed (we check that in |
| // CheckCompletedCXXClass). |
| CXXRecordDecl *InjectedClassName = nullptr; |
| for (NamedDecl *ND : CurClass->lookup(&II)) { |
| auto *RD = dyn_cast<CXXRecordDecl>(ND); |
| if (RD && RD->isInjectedClassName()) { |
| InjectedClassName = RD; |
| break; |
| } |
| } |
| if (!InjectedClassName) { |
| if (!CurClass->isInvalidDecl()) { |
| // FIXME: RequireCompleteDeclContext doesn't check dependent contexts |
| // properly. Work around it here for now. |
| Diag(SS.getLastQualifierNameLoc(), |
| diag::err_incomplete_nested_name_spec) << CurClass << SS.getRange(); |
| } |
| return ParsedType(); |
| } |
| |
| QualType T = Context.getTypeDeclType(InjectedClassName); |
| DiagnoseUseOfDecl(InjectedClassName, NameLoc); |
| MarkAnyDeclReferenced(NameLoc, InjectedClassName, /*OdrUse=*/false); |
| |
| return ParsedType::make(T); |
| } |
| |
| ParsedType Sema::getDestructorName(SourceLocation TildeLoc, |
| IdentifierInfo &II, |
| SourceLocation NameLoc, |
| Scope *S, CXXScopeSpec &SS, |
| ParsedType ObjectTypePtr, |
| bool EnteringContext) { |
| // Determine where to perform name lookup. |
| |
| // FIXME: This area of the standard is very messy, and the current |
| // wording is rather unclear about which scopes we search for the |
| // destructor name; see core issues 399 and 555. Issue 399 in |
| // particular shows where the current description of destructor name |
| // lookup is completely out of line with existing practice, e.g., |
| // this appears to be ill-formed: |
| // |
| // namespace N { |
| // template <typename T> struct S { |
| // ~S(); |
| // }; |
| // } |
| // |
| // void f(N::S<int>* s) { |
| // s->N::S<int>::~S(); |
| // } |
| // |
| // See also PR6358 and PR6359. |
| // For this reason, we're currently only doing the C++03 version of this |
| // code; the C++0x version has to wait until we get a proper spec. |
| QualType SearchType; |
| DeclContext *LookupCtx = nullptr; |
| bool isDependent = false; |
| bool LookInScope = false; |
| |
| if (SS.isInvalid()) |
| return nullptr; |
| |
| // If we have an object type, it's because we are in a |
| // pseudo-destructor-expression or a member access expression, and |
| // we know what type we're looking for. |
| if (ObjectTypePtr) |
| SearchType = GetTypeFromParser(ObjectTypePtr); |
| |
| if (SS.isSet()) { |
| NestedNameSpecifier *NNS = SS.getScopeRep(); |
| |
| bool AlreadySearched = false; |
| bool LookAtPrefix = true; |
| // C++11 [basic.lookup.qual]p6: |
| // If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, |
| // the type-names are looked up as types in the scope designated by the |
| // nested-name-specifier. Similarly, in a qualified-id of the form: |
| // |
| // nested-name-specifier[opt] class-name :: ~ class-name |
| // |
| // the second class-name is looked up in the same scope as the first. |
| // |
| // Here, we determine whether the code below is permitted to look at the |
| // prefix of the nested-name-specifier. |
| DeclContext *DC = computeDeclContext(SS, EnteringContext); |
| if (DC && DC->isFileContext()) { |
| AlreadySearched = true; |
| LookupCtx = DC; |
| isDependent = false; |
| } else if (DC && isa<CXXRecordDecl>(DC)) { |
| LookAtPrefix = false; |
| LookInScope = true; |
| } |
| |
| // The second case from the C++03 rules quoted further above. |
| NestedNameSpecifier *Prefix = nullptr; |
| if (AlreadySearched) { |
| // Nothing left to do. |
| } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) { |
| CXXScopeSpec PrefixSS; |
| PrefixSS.Adopt(NestedNameSpecifierLoc(Prefix, SS.location_data())); |
| LookupCtx = computeDeclContext(PrefixSS, EnteringContext); |
| isDependent = isDependentScopeSpecifier(PrefixSS); |
| } else if (ObjectTypePtr) { |
| LookupCtx = computeDeclContext(SearchType); |
| isDependent = SearchType->isDependentType(); |
| } else { |
| LookupCtx = computeDeclContext(SS, EnteringContext); |
| isDependent = LookupCtx && LookupCtx->isDependentContext(); |
| } |
| } else if (ObjectTypePtr) { |
| // C++ [basic.lookup.classref]p3: |
| // If the unqualified-id is ~type-name, the type-name is looked up |
| // in the context of the entire postfix-expression. If the type T |
| // of the object expression is of a class type C, the type-name is |
| // also looked up in the scope of class C. At least one of the |
| // lookups shall find a name that refers to (possibly |
| // cv-qualified) T. |
| LookupCtx = computeDeclContext(SearchType); |
| isDependent = SearchType->isDependentType(); |
| assert((isDependent || !SearchType->isIncompleteType()) && |
| "Caller should have completed object type"); |
| |
| LookInScope = true; |
| } else { |
| // Perform lookup into the current scope (only). |
| LookInScope = true; |
| } |
| |
| TypeDecl *NonMatchingTypeDecl = nullptr; |
| LookupResult Found(*this, &II, NameLoc, LookupOrdinaryName); |
| for (unsigned Step = 0; Step != 2; ++Step) { |
| // Look for the name first in the computed lookup context (if we |
| // have one) and, if that fails to find a match, in the scope (if |
| // we're allowed to look there). |
| Found.clear(); |
| if (Step == 0 && LookupCtx) { |
| if (RequireCompleteDeclContext(SS, LookupCtx)) |
| return nullptr; |
| LookupQualifiedName(Found, LookupCtx); |
| } else if (Step == 1 && LookInScope && S) { |
| LookupName(Found, S); |
| } else { |
| continue; |
| } |
| |
| // FIXME: Should we be suppressing ambiguities here? |
| if (Found.isAmbiguous()) |
| return nullptr; |
| |
| if (TypeDecl *Type = Found.getAsSingle<TypeDecl>()) { |
| QualType T = Context.getTypeDeclType(Type); |
| MarkAnyDeclReferenced(Type->getLocation(), Type, /*OdrUse=*/false); |
| |
| if (SearchType.isNull() || SearchType->isDependentType() || |
| Context.hasSameUnqualifiedType(T, SearchType)) { |
| // We found our type! |
| |
| return CreateParsedType(T, |
| Context.getTrivialTypeSourceInfo(T, NameLoc)); |
| } |
| |
| if (!SearchType.isNull()) |
| NonMatchingTypeDecl = Type; |
| } |
| |
| // If the name that we found is a class template name, and it is |
| // the same name as the template name in the last part of the |
| // nested-name-specifier (if present) or the object type, then |
| // this is the destructor for that class. |
| // FIXME: This is a workaround until we get real drafting for core |
| // issue 399, for which there isn't even an obvious direction. |
| if (ClassTemplateDecl *Template = Found.getAsSingle<ClassTemplateDecl>()) { |
| QualType MemberOfType; |
| if (SS.isSet()) { |
| if (DeclContext *Ctx = computeDeclContext(SS, EnteringContext)) { |
| // Figure out the type of the context, if it has one. |
| if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Ctx)) |
| MemberOfType = Context.getTypeDeclType(Record); |
| } |
| } |
| if (MemberOfType.isNull()) |
| MemberOfType = SearchType; |
| |
| if (MemberOfType.isNull()) |
| continue; |
| |
| // We're referring into a class template specialization. If the |
| // class template we found is the same as the template being |
| // specialized, we found what we are looking for. |
| if (const RecordType *Record = MemberOfType->getAs<RecordType>()) { |
| if (ClassTemplateSpecializationDecl *Spec |
| = dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) { |
| if (Spec->getSpecializedTemplate()->getCanonicalDecl() == |
| Template->getCanonicalDecl()) |
| return CreateParsedType( |
| MemberOfType, |
| Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc)); |
| } |
| |
| continue; |
| } |
| |
| // We're referring to an unresolved class template |
| // specialization. Determine whether we class template we found |
| // is the same as the template being specialized or, if we don't |
| // know which template is being specialized, that it at least |
| // has the same name. |
| if (const TemplateSpecializationType *SpecType |
| = MemberOfType->getAs<TemplateSpecializationType>()) { |
| TemplateName SpecName = SpecType->getTemplateName(); |
| |
| // The class template we found is the same template being |
| // specialized. |
| if (TemplateDecl *SpecTemplate = SpecName.getAsTemplateDecl()) { |
| if (SpecTemplate->getCanonicalDecl() == Template->getCanonicalDecl()) |
| return CreateParsedType( |
| MemberOfType, |
| Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc)); |
| |
| continue; |
| } |
| |
| // The class template we found has the same name as the |
| // (dependent) template name being specialized. |
| if (DependentTemplateName *DepTemplate |
| = SpecName.getAsDependentTemplateName()) { |
| if (DepTemplate->isIdentifier() && |
| DepTemplate->getIdentifier() == Template->getIdentifier()) |
| return CreateParsedType( |
| MemberOfType, |
| Context.getTrivialTypeSourceInfo(MemberOfType, NameLoc)); |
| |
| continue; |
| } |
| } |
| } |
| } |
| |
| if (isDependent) { |
| // We didn't find our type, but that's okay: it's dependent |
| // anyway. |
| |
| // FIXME: What if we have no nested-name-specifier? |
| QualType T = CheckTypenameType(ETK_None, SourceLocation(), |
| SS.getWithLocInContext(Context), |
| II, NameLoc); |
| return ParsedType::make(T); |
| } |
| |
| if (NonMatchingTypeDecl) { |
| QualType T = Context.getTypeDeclType(NonMatchingTypeDecl); |
| Diag(NameLoc, diag::err_destructor_expr_type_mismatch) |
| << T << SearchType; |
| Diag(NonMatchingTypeDecl->getLocation(), diag::note_destructor_type_here) |
| << T; |
| } else if (ObjectTypePtr) |
| Diag(NameLoc, diag::err_ident_in_dtor_not_a_type) |
| << &II; |
| else { |
| SemaDiagnosticBuilder DtorDiag = Diag(NameLoc, |
| diag::err_destructor_class_name); |
| if (S) { |
| const DeclContext *Ctx = S->getEntity(); |
| if (const CXXRecordDecl *Class = dyn_cast_or_null<CXXRecordDecl>(Ctx)) |
| DtorDiag << FixItHint::CreateReplacement(SourceRange(NameLoc), |
| Class->getNameAsString()); |
| } |
| } |
| |
| return nullptr; |
| } |
| |
| ParsedType Sema::getDestructorTypeForDecltype(const DeclSpec &DS, |
| ParsedType ObjectType) { |
| if (DS.getTypeSpecType() == DeclSpec::TST_error) |
| return nullptr; |
| |
| if (DS.getTypeSpecType() == DeclSpec::TST_decltype_auto) { |
| Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid); |
| return nullptr; |
| } |
| |
| assert(DS.getTypeSpecType() == DeclSpec::TST_decltype && |
| "unexpected type in getDestructorType"); |
| QualType T = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc()); |
| |
| // If we know the type of the object, check that the correct destructor |
| // type was named now; we can give better diagnostics this way. |
| QualType SearchType = GetTypeFromParser(ObjectType); |
| if (!SearchType.isNull() && !SearchType->isDependentType() && |
| !Context.hasSameUnqualifiedType(T, SearchType)) { |
| Diag(DS.getTypeSpecTypeLoc(), diag::err_destructor_expr_type_mismatch) |
| << T << SearchType; |
| return nullptr; |
| } |
| |
| return ParsedType::make(T); |
| } |
| |
| bool Sema::checkLiteralOperatorId(const CXXScopeSpec &SS, |
| const UnqualifiedId &Name) { |
| assert(Name.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId); |
| |
| if (!SS.isValid()) |
| return false; |
| |
| switch (SS.getScopeRep()->getKind()) { |
| case NestedNameSpecifier::Identifier: |
| case NestedNameSpecifier::TypeSpec: |
| case NestedNameSpecifier::TypeSpecWithTemplate: |
| // Per C++11 [over.literal]p2, literal operators can only be declared at |
| // namespace scope. Therefore, this unqualified-id cannot name anything. |
| // Reject it early, because we have no AST representation for this in the |
| // case where the scope is dependent. |
| Diag(Name.getBeginLoc(), diag::err_literal_operator_id_outside_namespace) |
| << SS.getScopeRep(); |
| return true; |
| |
| case NestedNameSpecifier::Global: |
| case NestedNameSpecifier::Super: |
| case NestedNameSpecifier::Namespace: |
| case NestedNameSpecifier::NamespaceAlias: |
| return false; |
| } |
| |
| llvm_unreachable("unknown nested name specifier kind"); |
| } |
| |
| /// Build a C++ typeid expression with a type operand. |
| ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, |
| SourceLocation TypeidLoc, |
| TypeSourceInfo *Operand, |
| SourceLocation RParenLoc) { |
| // C++ [expr.typeid]p4: |
| // The top-level cv-qualifiers of the lvalue expression or the type-id |
| // that is the operand of typeid are always ignored. |
| // If the type of the type-id is a class type or a reference to a class |
| // type, the class shall be completely-defined. |
| Qualifiers Quals; |
| QualType T |
| = Context.getUnqualifiedArrayType(Operand->getType().getNonReferenceType(), |
| Quals); |
| if (T->getAs<RecordType>() && |
| RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) |
| return ExprError(); |
| |
| if (T->isVariablyModifiedType()) |
| return ExprError(Diag(TypeidLoc, diag::err_variably_modified_typeid) << T); |
| |
| if (CheckQualifiedFunctionForTypeId(T, TypeidLoc)) |
| return ExprError(); |
| |
| return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), Operand, |
| SourceRange(TypeidLoc, RParenLoc)); |
| } |
| |
| /// Build a C++ typeid expression with an expression operand. |
| ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, |
| SourceLocation TypeidLoc, |
| Expr *E, |
| SourceLocation RParenLoc) { |
| bool WasEvaluated = false; |
| if (E && !E->isTypeDependent()) { |
| if (E->getType()->isPlaceholderType()) { |
| ExprResult result = CheckPlaceholderExpr(E); |
| if (result.isInvalid()) return ExprError(); |
| E = result.get(); |
| } |
| |
| QualType T = E->getType(); |
| if (const RecordType *RecordT = T->getAs<RecordType>()) { |
| CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl()); |
| // C++ [expr.typeid]p3: |
| // [...] If the type of the expression is a class type, the class |
| // shall be completely-defined. |
| if (RequireCompleteType(TypeidLoc, T, diag::err_incomplete_typeid)) |
| return ExprError(); |
| |
| // C++ [expr.typeid]p3: |
| // When typeid is applied to an expression other than an glvalue of a |
| // polymorphic class type [...] [the] expression is an unevaluated |
| // operand. [...] |
| if (RecordD->isPolymorphic() && E->isGLValue()) { |
| // The subexpression is potentially evaluated; switch the context |
| // and recheck the subexpression. |
| ExprResult Result = TransformToPotentiallyEvaluated(E); |
| if (Result.isInvalid()) return ExprError(); |
| E = Result.get(); |
| |
| // We require a vtable to query the type at run time. |
| MarkVTableUsed(TypeidLoc, RecordD); |
| WasEvaluated = true; |
| } |
| } |
| |
| ExprResult Result = CheckUnevaluatedOperand(E); |
| if (Result.isInvalid()) |
| return ExprError(); |
| E = Result.get(); |
| |
| // C++ [expr.typeid]p4: |
| // [...] If the type of the type-id is a reference to a possibly |
| // cv-qualified type, the result of the typeid expression refers to a |
| // std::type_info object representing the cv-unqualified referenced |
| // type. |
| Qualifiers Quals; |
| QualType UnqualT = Context.getUnqualifiedArrayType(T, Quals); |
| if (!Context.hasSameType(T, UnqualT)) { |
| T = UnqualT; |
| E = ImpCastExprToType(E, UnqualT, CK_NoOp, E->getValueKind()).get(); |
| } |
| } |
| |
| if (E->getType()->isVariablyModifiedType()) |
| return ExprError(Diag(TypeidLoc, diag::err_variably_modified_typeid) |
| << E->getType()); |
| else if (!inTemplateInstantiation() && |
| E->HasSideEffects(Context, WasEvaluated)) { |
| // The expression operand for typeid is in an unevaluated expression |
| // context, so side effects could result in unintended consequences. |
| Diag(E->getExprLoc(), WasEvaluated |
| ? diag::warn_side_effects_typeid |
| : diag::warn_side_effects_unevaluated_context); |
| } |
| |
| return new (Context) CXXTypeidExpr(TypeInfoType.withConst(), E, |
| SourceRange(TypeidLoc, RParenLoc)); |
| } |
| |
| /// ActOnCXXTypeidOfType - Parse typeid( type-id ) or typeid (expression); |
| ExprResult |
| Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, |
| bool isType, void *TyOrExpr, SourceLocation RParenLoc) { |
| // typeid is not supported in OpenCL. |
| if (getLangOpts().OpenCLCPlusPlus) { |
| return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) |
| << "typeid"); |
| } |
| |
| // Find the std::type_info type. |
| if (!getStdNamespace()) |
| return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); |
| |
| if (!CXXTypeInfoDecl) { |
| IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info"); |
| LookupResult R(*this, TypeInfoII, SourceLocation(), LookupTagName); |
| LookupQualifiedName(R, getStdNamespace()); |
| CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| // Microsoft's typeinfo doesn't have type_info in std but in the global |
| // namespace if _HAS_EXCEPTIONS is defined to 0. See PR13153. |
| if (!CXXTypeInfoDecl && LangOpts.MSVCCompat) { |
| LookupQualifiedName(R, Context.getTranslationUnitDecl()); |
| CXXTypeInfoDecl = R.getAsSingle<RecordDecl>(); |
| } |
| if (!CXXTypeInfoDecl) |
| return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); |
| } |
| |
| if (!getLangOpts().RTTI) { |
| return ExprError(Diag(OpLoc, diag::err_no_typeid_with_fno_rtti)); |
| } |
| |
| QualType TypeInfoType = Context.getTypeDeclType(CXXTypeInfoDecl); |
| |
| if (isType) { |
| // The operand is a type; handle it as such. |
| TypeSourceInfo *TInfo = nullptr; |
| QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), |
| &TInfo); |
| if (T.isNull()) |
| return ExprError(); |
| |
| if (!TInfo) |
| TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); |
| |
| return BuildCXXTypeId(TypeInfoType, OpLoc, TInfo, RParenLoc); |
| } |
| |
| // The operand is an expression. |
| return BuildCXXTypeId(TypeInfoType, OpLoc, (Expr*)TyOrExpr, RParenLoc); |
| } |
| |
| /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to |
| /// a single GUID. |
| static void |
| getUuidAttrOfType(Sema &SemaRef, QualType QT, |
| llvm::SmallSetVector<const UuidAttr *, 1> &UuidAttrs) { |
| // Optionally remove one level of pointer, reference or array indirection. |
| const Type *Ty = QT.getTypePtr(); |
| if (QT->isPointerType() || QT->isReferenceType()) |
| Ty = QT->getPointeeType().getTypePtr(); |
| else if (QT->isArrayType()) |
| Ty = Ty->getBaseElementTypeUnsafe(); |
| |
| const auto *TD = Ty->getAsTagDecl(); |
| if (!TD) |
| return; |
| |
| if (const auto *Uuid = TD->getMostRecentDecl()->getAttr<UuidAttr>()) { |
| UuidAttrs.insert(Uuid); |
| return; |
| } |
| |
| // __uuidof can grab UUIDs from template arguments. |
| if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) { |
| const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); |
| for (const TemplateArgument &TA : TAL.asArray()) { |
| const UuidAttr *UuidForTA = nullptr; |
| if (TA.getKind() == TemplateArgument::Type) |
| getUuidAttrOfType(SemaRef, TA.getAsType(), UuidAttrs); |
| else if (TA.getKind() == TemplateArgument::Declaration) |
| getUuidAttrOfType(SemaRef, TA.getAsDecl()->getType(), UuidAttrs); |
| |
| if (UuidForTA) |
| UuidAttrs.insert(UuidForTA); |
| } |
| } |
| } |
| |
| /// Build a Microsoft __uuidof expression with a type operand. |
| ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, |
| SourceLocation TypeidLoc, |
| TypeSourceInfo *Operand, |
| SourceLocation RParenLoc) { |
| StringRef UuidStr; |
| if (!Operand->getType()->isDependentType()) { |
| llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs; |
| getUuidAttrOfType(*this, Operand->getType(), UuidAttrs); |
| if (UuidAttrs.empty()) |
| return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); |
| if (UuidAttrs.size() > 1) |
| return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); |
| UuidStr = UuidAttrs.back()->getGuid(); |
| } |
| |
| return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), Operand, UuidStr, |
| SourceRange(TypeidLoc, RParenLoc)); |
| } |
| |
| /// Build a Microsoft __uuidof expression with an expression operand. |
| ExprResult Sema::BuildCXXUuidof(QualType TypeInfoType, |
| SourceLocation TypeidLoc, |
| Expr *E, |
| SourceLocation RParenLoc) { |
| StringRef UuidStr; |
| if (!E->getType()->isDependentType()) { |
| if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { |
| UuidStr = "00000000-0000-0000-0000-000000000000"; |
| } else { |
| llvm::SmallSetVector<const UuidAttr *, 1> UuidAttrs; |
| getUuidAttrOfType(*this, E->getType(), UuidAttrs); |
| if (UuidAttrs.empty()) |
| return ExprError(Diag(TypeidLoc, diag::err_uuidof_without_guid)); |
| if (UuidAttrs.size() > 1) |
| return ExprError(Diag(TypeidLoc, diag::err_uuidof_with_multiple_guids)); |
| UuidStr = UuidAttrs.back()->getGuid(); |
| } |
| } |
| |
| return new (Context) CXXUuidofExpr(TypeInfoType.withConst(), E, UuidStr, |
| SourceRange(TypeidLoc, RParenLoc)); |
| } |
| |
| /// ActOnCXXUuidof - Parse __uuidof( type-id ) or __uuidof (expression); |
| ExprResult |
| Sema::ActOnCXXUuidof(SourceLocation OpLoc, SourceLocation LParenLoc, |
| bool isType, void *TyOrExpr, SourceLocation RParenLoc) { |
| // If MSVCGuidDecl has not been cached, do the lookup. |
| if (!MSVCGuidDecl) { |
| IdentifierInfo *GuidII = &PP.getIdentifierTable().get("_GUID"); |
| LookupResult R(*this, GuidII, SourceLocation(), LookupTagName); |
| LookupQualifiedName(R, Context.getTranslationUnitDecl()); |
| MSVCGuidDecl = R.getAsSingle<RecordDecl>(); |
| if (!MSVCGuidDecl) |
| return ExprError(Diag(OpLoc, diag::err_need_header_before_ms_uuidof)); |
| } |
| |
| QualType GuidType = Context.getTypeDeclType(MSVCGuidDecl); |
| |
| if (isType) { |
| // The operand is a type; handle it as such. |
| TypeSourceInfo *TInfo = nullptr; |
| QualType T = GetTypeFromParser(ParsedType::getFromOpaquePtr(TyOrExpr), |
| &TInfo); |
| if (T.isNull()) |
| return ExprError(); |
| |
| if (!TInfo) |
| TInfo = Context.getTrivialTypeSourceInfo(T, OpLoc); |
| |
| return BuildCXXUuidof(GuidType, OpLoc, TInfo, RParenLoc); |
| } |
| |
| // The operand is an expression. |
| return BuildCXXUuidof(GuidType, OpLoc, (Expr*)TyOrExpr, RParenLoc); |
| } |
| |
| /// ActOnCXXBoolLiteral - Parse {true,false} literals. |
| ExprResult |
| Sema::ActOnCXXBoolLiteral(SourceLocation OpLoc, tok::TokenKind Kind) { |
| assert((Kind == tok::kw_true || Kind == tok::kw_false) && |
| "Unknown C++ Boolean value!"); |
| return new (Context) |
| CXXBoolLiteralExpr(Kind == tok::kw_true, Context.BoolTy, OpLoc); |
| } |
| |
| /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. |
| ExprResult |
| Sema::ActOnCXXNullPtrLiteral(SourceLocation Loc) { |
| return new (Context) CXXNullPtrLiteralExpr(Context.NullPtrTy, Loc); |
| } |
| |
| /// ActOnCXXThrow - Parse throw expressions. |
| ExprResult |
| Sema::ActOnCXXThrow(Scope *S, SourceLocation OpLoc, Expr *Ex) { |
| bool IsThrownVarInScope = false; |
| if (Ex) { |
| // C++0x [class.copymove]p31: |
| // When certain criteria are met, an implementation is allowed to omit the |
| // copy/move construction of a class object [...] |
| // |
| // - in a throw-expression, when the operand is the name of a |
| // non-volatile automatic object (other than a function or catch- |
| // clause parameter) whose scope does not extend beyond the end of the |
| // innermost enclosing try-block (if there is one), the copy/move |
| // operation from the operand to the exception object (15.1) can be |
| // omitted by constructing the automatic object directly into the |
| // exception object |
| if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex->IgnoreParens())) |
| if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { |
| if (Var->hasLocalStorage() && !Var->getType().isVolatileQualified()) { |
| for( ; S; S = S->getParent()) { |
| if (S->isDeclScope(Var)) { |
| IsThrownVarInScope = true; |
| break; |
| } |
| |
| if (S->getFlags() & |
| (Scope::FnScope | Scope::ClassScope | Scope::BlockScope | |
| Scope::FunctionPrototypeScope | Scope::ObjCMethodScope | |
| Scope::TryScope)) |
| break; |
| } |
| } |
| } |
| } |
| |
| return BuildCXXThrow(OpLoc, Ex, IsThrownVarInScope); |
| } |
| |
| ExprResult Sema::BuildCXXThrow(SourceLocation OpLoc, Expr *Ex, |
| bool IsThrownVarInScope) { |
| // Don't report an error if 'throw' is used in system headers. |
| if (!getLangOpts().CXXExceptions && |
| !getSourceManager().isInSystemHeader(OpLoc) && !getLangOpts().CUDA) { |
| // Delay error emission for the OpenMP device code. |
| targetDiag(OpLoc, diag::err_exceptions_disabled) << "throw"; |
| } |
| |
| // Exceptions aren't allowed in CUDA device code. |
| if (getLangOpts().CUDA) |
| CUDADiagIfDeviceCode(OpLoc, diag::err_cuda_device_exceptions) |
| << "throw" << CurrentCUDATarget(); |
| |
| if (getCurScope() && getCurScope()->isOpenMPSimdDirectiveScope()) |
| Diag(OpLoc, diag::err_omp_simd_region_cannot_use_stmt) << "throw"; |
| |
| if (Ex && !Ex->isTypeDependent()) { |
| QualType ExceptionObjectTy = Context.getExceptionObjectType(Ex->getType()); |
| if (CheckCXXThrowOperand(OpLoc, ExceptionObjectTy, Ex)) |
| return ExprError(); |
| |
| // Initialize the exception result. This implicitly weeds out |
| // abstract types or types with inaccessible copy constructors. |
| |
| // C++0x [class.copymove]p31: |
| // When certain criteria are met, an implementation is allowed to omit the |
| // copy/move construction of a class object [...] |
| // |
| // - in a throw-expression, when the operand is the name of a |
| // non-volatile automatic object (other than a function or |
| // catch-clause |
| // parameter) whose scope does not extend beyond the end of the |
| // innermost enclosing try-block (if there is one), the copy/move |
| // operation from the operand to the exception object (15.1) can be |
| // omitted by constructing the automatic object directly into the |
| // exception object |
| const VarDecl *NRVOVariable = nullptr; |
| if (IsThrownVarInScope) |
| NRVOVariable = getCopyElisionCandidate(QualType(), Ex, CES_Strict); |
| |
| InitializedEntity Entity = InitializedEntity::InitializeException( |
| OpLoc, ExceptionObjectTy, |
| /*NRVO=*/NRVOVariable != nullptr); |
| ExprResult Res = PerformMoveOrCopyInitialization( |
| Entity, NRVOVariable, QualType(), Ex, IsThrownVarInScope); |
| if (Res.isInvalid()) |
| return ExprError(); |
| Ex = Res.get(); |
| } |
| |
| return new (Context) |
| CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope); |
| } |
| |
| static void |
| collectPublicBases(CXXRecordDecl *RD, |
| llvm::DenseMap<CXXRecordDecl *, unsigned> &SubobjectsSeen, |
| llvm::SmallPtrSetImpl<CXXRecordDecl *> &VBases, |
| llvm::SetVector<CXXRecordDecl *> &PublicSubobjectsSeen, |
| bool ParentIsPublic) { |
| for (const CXXBaseSpecifier &BS : RD->bases()) { |
| CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); |
| bool NewSubobject; |
| // Virtual bases constitute the same subobject. Non-virtual bases are |
| // always distinct subobjects. |
| if (BS.isVirtual()) |
| NewSubobject = VBases.insert(BaseDecl).second; |
| else |
| NewSubobject = true; |
| |
| if (NewSubobject) |
| ++SubobjectsSeen[BaseDecl]; |
| |
| // Only add subobjects which have public access throughout the entire chain. |
| bool PublicPath = ParentIsPublic && BS.getAccessSpecifier() == AS_public; |
| if (PublicPath) |
| PublicSubobjectsSeen.insert(BaseDecl); |
| |
| // Recurse on to each base subobject. |
| collectPublicBases(BaseDecl, SubobjectsSeen, VBases, PublicSubobjectsSeen, |
| PublicPath); |
| } |
| } |
| |
| static void getUnambiguousPublicSubobjects( |
| CXXRecordDecl *RD, llvm::SmallVectorImpl<CXXRecordDecl *> &Objects) { |
| llvm::DenseMap<CXXRecordDecl *, unsigned> SubobjectsSeen; |
| llvm::SmallSet<CXXRecordDecl *, 2> VBases; |
| llvm::SetVector<CXXRecordDecl *> PublicSubobjectsSeen; |
| SubobjectsSeen[RD] = 1; |
| PublicSubobjectsSeen.insert(RD); |
| collectPublicBases(RD, SubobjectsSeen, VBases, PublicSubobjectsSeen, |
| /*ParentIsPublic=*/true); |
| |
| for (CXXRecordDecl *PublicSubobject : PublicSubobjectsSeen) { |
| // Skip ambiguous objects. |
| if (SubobjectsSeen[PublicSubobject] > 1) |
| continue; |
| |
| Objects.push_back(PublicSubobject); |
| } |
| } |
| |
| /// CheckCXXThrowOperand - Validate the operand of a throw. |
| bool Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, |
| QualType ExceptionObjectTy, Expr *E) { |
| // If the type of the exception would be an incomplete type or a pointer |
| // to an incomplete type other than (cv) void the program is ill-formed. |
| QualType Ty = ExceptionObjectTy; |
| bool isPointer = false; |
| if (const PointerType* Ptr = Ty->getAs<PointerType>()) { |
| Ty = Ptr->getPointeeType(); |
| isPointer = true; |
| } |
| if (!isPointer || !Ty->isVoidType()) { |
| if (RequireCompleteType(ThrowLoc, Ty, |
| isPointer ? diag::err_throw_incomplete_ptr |
| : diag::err_throw_incomplete, |
| E->getSourceRange())) |
| return true; |
| |
| if (RequireNonAbstractType(ThrowLoc, ExceptionObjectTy, |
| diag::err_throw_abstract_type, E)) |
| return true; |
| } |
| |
| // If the exception has class type, we need additional handling. |
| CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); |
| if (!RD) |
| return false; |
| |
| // If we are throwing a polymorphic class type or pointer thereof, |
| // exception handling will make use of the vtable. |
| MarkVTableUsed(ThrowLoc, RD); |
| |
| // If a pointer is thrown, the referenced object will not be destroyed. |
| if (isPointer) |
| return false; |
| |
| // If the class has a destructor, we must be able to call it. |
| if (!RD->hasIrrelevantDestructor()) { |
| if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { |
| MarkFunctionReferenced(E->getExprLoc(), Destructor); |
| CheckDestructorAccess(E->getExprLoc(), Destructor, |
| PDiag(diag::err_access_dtor_exception) << Ty); |
| if (DiagnoseUseOfDecl(Destructor, E->getExprLoc())) |
| return true; |
| } |
| } |
| |
| // The MSVC ABI creates a list of all types which can catch the exception |
| // object. This list also references the appropriate copy constructor to call |
| // if the object is caught by value and has a non-trivial copy constructor. |
| if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { |
| // We are only interested in the public, unambiguous bases contained within |
| // the exception object. Bases which are ambiguous or otherwise |
| // inaccessible are not catchable types. |
| llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects; |
| getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects); |
| |
| for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) { |
| // Attempt to lookup the copy constructor. Various pieces of machinery |
| // will spring into action, like template instantiation, which means this |
| // cannot be a simple walk of the class's decls. Instead, we must perform |
| // lookup and overload resolution. |
| CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0); |
| if (!CD) |
| continue; |
| |
| // Mark the constructor referenced as it is used by this throw expression. |
| MarkFunctionReferenced(E->getExprLoc(), CD); |
| |
| // Skip this copy constructor if it is trivial, we don't need to record it |
| // in the catchable type data. |
| if (CD->isTrivial()) |
| continue; |
| |
| // The copy constructor is non-trivial, create a mapping from this class |
| // type to this constructor. |
| // N.B. The selection of copy constructor is not sensitive to this |
| // particular throw-site. Lookup will be performed at the catch-site to |
| // ensure that the copy constructor is, in fact, accessible (via |
| // friendship or any other means). |
| Context.addCopyConstructorForExceptionObject(Subobject, CD); |
| |
| // We don't keep the instantiated default argument expressions around so |
| // we must rebuild them here. |
| for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) { |
| if (CheckCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I))) |
| return true; |
| } |
| } |
| } |
| |
| // Under the Itanium C++ ABI, memory for the exception object is allocated by |
| // the runtime with no ability for the compiler to request additional |
| // alignment. Warn if the exception type requires alignment beyond the minimum |
| // guaranteed by the target C++ runtime. |
| if (Context.getTargetInfo().getCXXABI().isItaniumFamily()) { |
| CharUnits TypeAlign = Context.getTypeAlignInChars(Ty); |
| CharUnits ExnObjAlign = Context.getExnObjectAlignment(); |
| if (ExnObjAlign < TypeAlign) { |
| Diag(ThrowLoc, diag::warn_throw_underaligned_obj); |
| Diag(ThrowLoc, diag::note_throw_underaligned_obj) |
| << Ty << (unsigned)TypeAlign.getQuantity() |
| << (unsigned)ExnObjAlign.getQuantity(); |
| } |
| } |
| |
| return false; |
| } |
| |
| static QualType adjustCVQualifiersForCXXThisWithinLambda( |
| ArrayRef<FunctionScopeInfo *> FunctionScopes, QualType ThisTy, |
| DeclContext *CurSemaContext, ASTContext &ASTCtx) { |
| |
| QualType ClassType = ThisTy->getPointeeType(); |
| LambdaScopeInfo *CurLSI = nullptr; |
| DeclContext *CurDC = CurSemaContext; |
| |
| // Iterate through the stack of lambdas starting from the innermost lambda to |
| // the outermost lambda, checking if '*this' is ever captured by copy - since |
| // that could change the cv-qualifiers of the '*this' object. |
| // The object referred to by '*this' starts out with the cv-qualifiers of its |
| // member function. We then start with the innermost lambda and iterate |
| // outward checking to see if any lambda performs a by-copy capture of '*this' |
| // - and if so, any nested lambda must respect the 'constness' of that |
| // capturing lamdbda's call operator. |
| // |
| |
| // Since the FunctionScopeInfo stack is representative of the lexical |
| // nesting of the lambda expressions during initial parsing (and is the best |
| // place for querying information about captures about lambdas that are |
| // partially processed) and perhaps during instantiation of function templates |
| // that contain lambda expressions that need to be transformed BUT not |
| // necessarily during instantiation of a nested generic lambda's function call |
| // operator (which might even be instantiated at the end of the TU) - at which |
| // time the DeclContext tree is mature enough to query capture information |
| // reliably - we use a two pronged approach to walk through all the lexically |
| // enclosing lambda expressions: |
| // |
| // 1) Climb down the FunctionScopeInfo stack as long as each item represents |
| // a Lambda (i.e. LambdaScopeInfo) AND each LSI's 'closure-type' is lexically |
| // enclosed by the call-operator of the LSI below it on the stack (while |
| // tracking the enclosing DC for step 2 if needed). Note the topmost LSI on |
| // the stack represents the innermost lambda. |
| // |
| // 2) If we run out of enclosing LSI's, check if the enclosing DeclContext |
| // represents a lambda's call operator. If it does, we must be instantiating |
| // a generic lambda's call operator (represented by the Current LSI, and |
| // should be the only scenario where an inconsistency between the LSI and the |
| // DeclContext should occur), so climb out the DeclContexts if they |
| // represent lambdas, while querying the corresponding closure types |
| // regarding capture information. |
| |
| // 1) Climb down the function scope info stack. |
| for (int I = FunctionScopes.size(); |
| I-- && isa<LambdaScopeInfo>(FunctionScopes[I]) && |
| (!CurLSI || !CurLSI->Lambda || CurLSI->Lambda->getDeclContext() == |
| cast<LambdaScopeInfo>(FunctionScopes[I])->CallOperator); |
| CurDC = getLambdaAwareParentOfDeclContext(CurDC)) { |
| CurLSI = cast<LambdaScopeInfo>(FunctionScopes[I]); |
| |
| if (!CurLSI->isCXXThisCaptured()) |
| continue; |
| |
| auto C = CurLSI->getCXXThisCapture(); |
| |
| if (C.isCopyCapture()) { |
| ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); |
| if (CurLSI->CallOperator->isConst()) |
| ClassType.addConst(); |
| return ASTCtx.getPointerType(ClassType); |
| } |
| } |
| |
| // 2) We've run out of ScopeInfos but check if CurDC is a lambda (which can |
| // happen during instantiation of its nested generic lambda call operator) |
| if (isLambdaCallOperator(CurDC)) { |
| assert(CurLSI && "While computing 'this' capture-type for a generic " |
| "lambda, we must have a corresponding LambdaScopeInfo"); |
| assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator) && |
| "While computing 'this' capture-type for a generic lambda, when we " |
| "run out of enclosing LSI's, yet the enclosing DC is a " |
| "lambda-call-operator we must be (i.e. Current LSI) in a generic " |
| "lambda call oeprator"); |
| assert(CurDC == getLambdaAwareParentOfDeclContext(CurLSI->CallOperator)); |
| |
| auto IsThisCaptured = |
| [](CXXRecordDecl *Closure, bool &IsByCopy, bool &IsConst) { |
| IsConst = false; |
| IsByCopy = false; |
| for (auto &&C : Closure->captures()) { |
| if (C.capturesThis()) { |
| if (C.getCaptureKind() == LCK_StarThis) |
| IsByCopy = true; |
| if (Closure->getLambdaCallOperator()->isConst()) |
| IsConst = true; |
| return true; |
| } |
| } |
| return false; |
| }; |
| |
| bool IsByCopyCapture = false; |
| bool IsConstCapture = false; |
| CXXRecordDecl *Closure = cast<CXXRecordDecl>(CurDC->getParent()); |
| while (Closure && |
| IsThisCaptured(Closure, IsByCopyCapture, IsConstCapture)) { |
| if (IsByCopyCapture) { |
| ClassType.removeLocalCVRQualifiers(Qualifiers::CVRMask); |
| if (IsConstCapture) |
| ClassType.addConst(); |
| return ASTCtx.getPointerType(ClassType); |
| } |
| Closure = isLambdaCallOperator(Closure->getParent()) |
| ? cast<CXXRecordDecl>(Closure->getParent()->getParent()) |
| : nullptr; |
| } |
| } |
| return ASTCtx.getPointerType(ClassType); |
| } |
| |
| QualType Sema::getCurrentThisType() { |
| DeclContext *DC = getFunctionLevelDeclContext(); |
| QualType ThisTy = CXXThisTypeOverride; |
| |
| if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(DC)) { |
| if (method && method->isInstance()) |
| ThisTy = method->getThisType(); |
| } |
| |
| if (ThisTy.isNull() && isLambdaCallOperator(CurContext) && |
| inTemplateInstantiation()) { |
| |
| assert(isa<CXXRecordDecl>(DC) && |
| "Trying to get 'this' type from static method?"); |
| |
| // This is a lambda call operator that is being instantiated as a default |
| // initializer. DC must point to the enclosing class type, so we can recover |
| // the 'this' type from it. |
| |
| QualType ClassTy = Context.getTypeDeclType(cast<CXXRecordDecl>(DC)); |
| // There are no cv-qualifiers for 'this' within default initializers, |
| // per [expr.prim.general]p4. |
| ThisTy = Context.getPointerType(ClassTy); |
| } |
| |
| // If we are within a lambda's call operator, the cv-qualifiers of 'this' |
| // might need to be adjusted if the lambda or any of its enclosing lambda's |
| // captures '*this' by copy. |
| if (!ThisTy.isNull() && isLambdaCallOperator(CurContext)) |
| return adjustCVQualifiersForCXXThisWithinLambda(FunctionScopes, ThisTy, |
| CurContext, Context); |
| return ThisTy; |
| } |
| |
| Sema::CXXThisScopeRAII::CXXThisScopeRAII(Sema &S, |
| Decl *ContextDecl, |
| Qualifiers CXXThisTypeQuals, |
| bool Enabled) |
| : S(S), OldCXXThisTypeOverride(S.CXXThisTypeOverride), Enabled(false) |
| { |
| if (!Enabled || !ContextDecl) |
| return; |
| |
| CXXRecordDecl *Record = nullptr; |
| if (ClassTemplateDecl *Template = dyn_cast<ClassTemplateDecl>(ContextDecl)) |
| Record = Template->getTemplatedDecl(); |
| else |
| Record = cast<CXXRecordDecl>(ContextDecl); |
| |
| QualType T = S.Context.getRecordType(Record); |
| T = S.getASTContext().getQualifiedType(T, CXXThisTypeQuals); |
| |
| S.CXXThisTypeOverride = S.Context.getPointerType(T); |
| |
| this->Enabled = true; |
| } |
| |
| |
| Sema::CXXThisScopeRAII::~CXXThisScopeRAII() { |
| if (Enabled) { |
| S.CXXThisTypeOverride = OldCXXThisTypeOverride; |
| } |
| } |
| |
| bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, |
| bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt, |
| const bool ByCopy) { |
| // We don't need to capture this in an unevaluated context. |
| if (isUnevaluatedContext() && !Explicit) |
| return true; |
| |
| assert((!ByCopy || Explicit) && "cannot implicitly capture *this by value"); |
| |
| const int MaxFunctionScopesIndex = FunctionScopeIndexToStopAt |
| ? *FunctionScopeIndexToStopAt |
| : FunctionScopes.size() - 1; |
| |
| // Check that we can capture the *enclosing object* (referred to by '*this') |
| // by the capturing-entity/closure (lambda/block/etc) at |
| // MaxFunctionScopesIndex-deep on the FunctionScopes stack. |
| |
| // Note: The *enclosing object* can only be captured by-value by a |
| // closure that is a lambda, using the explicit notation: |
| // [*this] { ... }. |
| // Every other capture of the *enclosing object* results in its by-reference |
| // capture. |
| |
| // For a closure 'L' (at MaxFunctionScopesIndex in the FunctionScopes |
| // stack), we can capture the *enclosing object* only if: |
| // - 'L' has an explicit byref or byval capture of the *enclosing object* |
| // - or, 'L' has an implicit capture. |
| // AND |
| // -- there is no enclosing closure |
| // -- or, there is some enclosing closure 'E' that has already captured the |
| // *enclosing object*, and every intervening closure (if any) between 'E' |
| // and 'L' can implicitly capture the *enclosing object*. |
| // -- or, every enclosing closure can implicitly capture the |
| // *enclosing object* |
| |
| |
| unsigned NumCapturingClosures = 0; |
| for (int idx = MaxFunctionScopesIndex; idx >= 0; idx--) { |
| if (CapturingScopeInfo *CSI = |
| dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) { |
| if (CSI->CXXThisCaptureIndex != 0) { |
| // 'this' is already being captured; there isn't anything more to do. |
| CSI->Captures[CSI->CXXThisCaptureIndex - 1].markUsed(BuildAndDiagnose); |
| break; |
| } |
| LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI); |
| if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) { |
| // This context can't implicitly capture 'this'; fail out. |
| if (BuildAndDiagnose) |
| Diag(Loc, diag::err_this_capture) |
| << (Explicit && idx == MaxFunctionScopesIndex); |
| return true; |
| } |
| if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref || |
| CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval || |
| CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block || |
| CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_CapturedRegion || |
| (Explicit && idx == MaxFunctionScopesIndex)) { |
| // Regarding (Explicit && idx == MaxFunctionScopesIndex): only the first |
| // iteration through can be an explicit capture, all enclosing closures, |
| // if any, must perform implicit captures. |
| |
| // This closure can capture 'this'; continue looking upwards. |
| NumCapturingClosures++; |
| continue; |
| } |
| // This context can't implicitly capture 'this'; fail out. |
| if (BuildAndDiagnose) |
| Diag(Loc, diag::err_this_capture) |
| << (Explicit && idx == MaxFunctionScopesIndex); |
| return true; |
| } |
| break; |
| } |
| if (!BuildAndDiagnose) return false; |
| |
| // If we got here, then the closure at MaxFunctionScopesIndex on the |
| // FunctionScopes stack, can capture the *enclosing object*, so capture it |
| // (including implicit by-reference captures in any enclosing closures). |
| |
| // In the loop below, respect the ByCopy flag only for the closure requesting |
| // the capture (i.e. first iteration through the loop below). Ignore it for |
| // all enclosing closure's up to NumCapturingClosures (since they must be |
| // implicitly capturing the *enclosing object* by reference (see loop |
| // above)). |
| assert((!ByCopy || |
| dyn_cast<LambdaScopeInfo>(FunctionScopes[MaxFunctionScopesIndex])) && |
| "Only a lambda can capture the enclosing object (referred to by " |
| "*this) by copy"); |
| QualType ThisTy = getCurrentThisType(); |
| for (int idx = MaxFunctionScopesIndex; NumCapturingClosures; |
| --idx, --NumCapturingClosures) { |
| CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]); |
| |
| // The type of the corresponding data member (not a 'this' pointer if 'by |
| // copy'). |
| QualType CaptureType = ThisTy; |
| if (ByCopy) { |
| // If we are capturing the object referred to by '*this' by copy, ignore |
| // any cv qualifiers inherited from the type of the member function for |
| // the type of the closure-type's corresponding data member and any use |
| // of 'this'. |
| CaptureType = ThisTy->getPointeeType(); |
| CaptureType.removeLocalCVRQualifiers(Qualifiers::CVRMask); |
| } |
| |
| bool isNested = NumCapturingClosures > 1; |
| CSI->addThisCapture(isNested, Loc, CaptureType, ByCopy); |
| } |
| return false; |
| } |
| |
| ExprResult Sema::ActOnCXXThis(SourceLocation Loc) { |
| /// C++ 9.3.2: In the body of a non-static member function, the keyword this |
| /// is a non-lvalue expression whose value is the address of the object for |
| /// which the function is called. |
| |
| QualType ThisTy = getCurrentThisType(); |
| if (ThisTy.isNull()) |
| return Diag(Loc, diag::err_invalid_this_use); |
| return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false); |
| } |
| |
| Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, |
| bool IsImplicit) { |
| auto *This = new (Context) CXXThisExpr(Loc, Type, IsImplicit); |
| MarkThisReferenced(This); |
| return This; |
| } |
| |
| void Sema::MarkThisReferenced(CXXThisExpr *This) { |
| CheckCXXThisCapture(This->getExprLoc()); |
| } |
| |
| bool Sema::isThisOutsideMemberFunctionBody(QualType BaseType) { |
| // If we're outside the body of a member function, then we'll have a specified |
| // type for 'this'. |
| if (CXXThisTypeOverride.isNull()) |
| return false; |
| |
| // Determine whether we're looking into a class that's currently being |
| // defined. |
| CXXRecordDecl *Class = BaseType->getAsCXXRecordDecl(); |
| return Class && Class->isBeingDefined(); |
| } |
| |
| /// Parse construction of a specified type. |
| /// Can be interpreted either as function-style casting ("int(x)") |
| /// or class type construction ("ClassType(x,y,z)") |
| /// or creation of a value-initialized type ("int()"). |
| ExprResult |
| Sema::ActOnCXXTypeConstructExpr(ParsedType TypeRep, |
| SourceLocation LParenOrBraceLoc, |
| MultiExprArg exprs, |
| SourceLocation RParenOrBraceLoc, |
| bool ListInitialization) { |
| if (!TypeRep) |
| return ExprError(); |
| |
| TypeSourceInfo *TInfo; |
| QualType Ty = GetTypeFromParser(TypeRep, &TInfo); |
| if (!TInfo) |
| TInfo = Context.getTrivialTypeSourceInfo(Ty, SourceLocation()); |
| |
| auto Result = BuildCXXTypeConstructExpr(TInfo, LParenOrBraceLoc, exprs, |
| RParenOrBraceLoc, ListInitialization); |
| // Avoid creating a non-type-dependent expression that contains typos. |
| // Non-type-dependent expressions are liable to be discarded without |
| // checking for embedded typos. |
| if (!Result.isInvalid() && Result.get()->isInstantiationDependent() && |
| !Result.get()->isTypeDependent()) |
| Result = CorrectDelayedTyposInExpr(Result.get()); |
| return Result; |
| } |
| |
| ExprResult |
| Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, |
| SourceLocation LParenOrBraceLoc, |
| MultiExprArg Exprs, |
| SourceLocation RParenOrBraceLoc, |
| bool ListInitialization) { |
| QualType Ty = TInfo->getType(); |
| SourceLocation TyBeginLoc = TInfo->getTypeLoc().getBeginLoc(); |
| |
| if (Ty->isDependentType() || CallExpr::hasAnyTypeDependentArguments(Exprs)) { |
| // FIXME: CXXUnresolvedConstructExpr does not model list-initialization |
| // directly. We work around this by dropping the locations of the braces. |
| SourceRange Locs = ListInitialization |
| ? SourceRange() |
| : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); |
| return CXXUnresolvedConstructExpr::Create(Context, TInfo, Locs.getBegin(), |
| Exprs, Locs.getEnd()); |
| } |
| |
| assert((!ListInitialization || |
| (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) && |
| "List initialization must have initializer list as expression."); |
| SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc); |
| |
| InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); |
| InitializationKind Kind = |
| Exprs.size() |
| ? ListInitialization |
| ? InitializationKind::CreateDirectList( |
| TyBeginLoc, LParenOrBraceLoc, RParenOrBraceLoc) |
| : InitializationKind::CreateDirect(TyBeginLoc, LParenOrBraceLoc, |
| RParenOrBraceLoc) |
| : InitializationKind::CreateValue(TyBeginLoc, LParenOrBraceLoc, |
| RParenOrBraceLoc); |
| |
| // C++1z [expr.type.conv]p1: |
| // If the type is a placeholder for a deduced class type, [...perform class |
| // template argument deduction...] |
| DeducedType *Deduced = Ty->getContainedDeducedType(); |
| if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { |
| Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity, |
| Kind, Exprs); |
| if (Ty.isNull()) |
| return ExprError(); |
| Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); |
| } |
| |
| // C++ [expr.type.conv]p1: |
| // If the expression list is a parenthesized single expression, the type |
| // conversion expression is equivalent (in definedness, and if defined in |
| // meaning) to the corresponding cast expression. |
| if (Exprs.size() == 1 && !ListInitialization && |
| !isa<InitListExpr>(Exprs[0])) { |
| Expr *Arg = Exprs[0]; |
| return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenOrBraceLoc, Arg, |
| RParenOrBraceLoc); |
| } |
| |
| // For an expression of the form T(), T shall not be an array type. |
| QualType ElemTy = Ty; |
| if (Ty->isArrayType()) { |
| if (!ListInitialization) |
| return ExprError(Diag(TyBeginLoc, diag::err_value_init_for_array_type) |
| << FullRange); |
| ElemTy = Context.getBaseElementType(Ty); |
| } |
| |
| // There doesn't seem to be an explicit rule against this but sanity demands |
| // we only construct objects with object types. |
| if (Ty->isFunctionType()) |
| return ExprError(Diag(TyBeginLoc, diag::err_init_for_function_type) |
| << Ty << FullRange); |
| |
| // C++17 [expr.type.conv]p2: |
| // If the type is cv void and the initializer is (), the expression is a |
| // prvalue of the specified type that performs no initialization. |
| if (!Ty->isVoidType() && |
| RequireCompleteType(TyBeginLoc, ElemTy, |
| diag::err_invalid_incomplete_type_use, FullRange)) |
| return ExprError(); |
| |
| // Otherwise, the expression is a prvalue of the specified type whose |
| // result object is direct-initialized (11.6) with the initializer. |
| InitializationSequence InitSeq(*this, Entity, Kind, Exprs); |
| ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs); |
| |
| if (Result.isInvalid()) |
| return Result; |
| |
| Expr *Inner = Result.get(); |
| if (CXXBindTemporaryExpr *BTE = dyn_cast_or_null<CXXBindTemporaryExpr>(Inner)) |
| Inner = BTE->getSubExpr(); |
| if (!isa<CXXTemporaryObjectExpr>(Inner) && |
| !isa<CXXScalarValueInitExpr>(Inner)) { |
| // If we created a CXXTemporaryObjectExpr, that node also represents the |
| // functional cast. Otherwise, create an explicit cast to represent |
| // the syntactic form of a functional-style cast that was used here. |
| // |
| // FIXME: Creating a CXXFunctionalCastExpr around a CXXConstructExpr |
| // would give a more consistent AST representation than using a |
| // CXXTemporaryObjectExpr. It's also weird that the functional cast |
| // is sometimes handled by initialization and sometimes not. |
| QualType ResultType = Result.get()->getType(); |
| SourceRange Locs = ListInitialization |
| ? SourceRange() |
| : SourceRange(LParenOrBraceLoc, RParenOrBraceLoc); |
| Result = CXXFunctionalCastExpr::Create( |
| Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, |
| Result.get(), /*Path=*/nullptr, Locs.getBegin(), Locs.getEnd()); |
| } |
| |
| return Result; |
| } |
| |
| bool Sema::isUsualDeallocationFunction(const CXXMethodDecl *Method) { |
| // [CUDA] Ignore this function, if we can't call it. |
| const FunctionDecl *Caller = dyn_cast<FunctionDecl>(CurContext); |
| if (getLangOpts().CUDA && |
| IdentifyCUDAPreference(Caller, Method) <= CFP_WrongSide) |
| return false; |
| |
| SmallVector<const FunctionDecl*, 4> PreventedBy; |
| bool Result = Method->isUsualDeallocationFunction(PreventedBy); |
| |
| if (Result || !getLangOpts().CUDA || PreventedBy.empty()) |
| return Result; |
| |
| // In case of CUDA, return true if none of the 1-argument deallocator |
| // functions are actually callable. |
| return llvm::none_of(PreventedBy, [&](const FunctionDecl *FD) { |
| assert(FD->getNumParams() == 1 && |
| "Only single-operand functions should be in PreventedBy"); |
| return IdentifyCUDAPreference(Caller, FD) >= CFP_HostDevice; |
| }); |
| } |
| |
| /// Determine whether the given function is a non-placement |
| /// deallocation function. |
| static bool isNonPlacementDeallocationFunction(Sema &S, FunctionDecl *FD) { |
| if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FD)) |
| return S.isUsualDeallocationFunction(Method); |
| |
| if (FD->getOverloadedOperator() != OO_Delete && |
| FD->getOverloadedOperator() != OO_Array_Delete) |
| return false; |
| |
| unsigned UsualParams = 1; |
| |
| if (S.getLangOpts().SizedDeallocation && UsualParams < FD->getNumParams() && |
| S.Context.hasSameUnqualifiedType( |
| FD->getParamDecl(UsualParams)->getType(), |
| S.Context.getSizeType())) |
| ++UsualParams; |
| |
| if (S.getLangOpts().AlignedAllocation && UsualParams < FD->getNumParams() && |
| S.Context.hasSameUnqualifiedType( |
| FD->getParamDecl(UsualParams)->getType(), |
| S.Context.getTypeDeclType(S.getStdAlignValT()))) |
| ++UsualParams; |
| |
| return UsualParams == FD->getNumParams(); |
| } |
| |
| namespace { |
| struct UsualDeallocFnInfo { |
| UsualDeallocFnInfo() : Found(), FD(nullptr) {} |
| UsualDeallocFnInfo(Sema &S, DeclAccessPair Found) |
| : Found(Found), FD(dyn_cast<FunctionDecl>(Found->getUnderlyingDecl())), |
| Destroying(false), HasSizeT(false), HasAlignValT(false), |
| CUDAPref(Sema::CFP_Native) { |
| // A function template declaration is never a usual deallocation function. |
| if (!FD) |
| return; |
| unsigned NumBaseParams = 1; |
| if (FD->isDestroyingOperatorDelete()) { |
| Destroying = true; |
| ++NumBaseParams; |
| } |
| |
| if (NumBaseParams < FD->getNumParams() && |
| S.Context.hasSameUnqualifiedType( |
| FD->getParamDecl(NumBaseParams)->getType(), |
| S.Context.getSizeType())) { |
| ++NumBaseParams; |
| HasSizeT = true; |
| } |
| |
| if (NumBaseParams < FD->getNumParams() && |
| FD->getParamDecl(NumBaseParams)->getType()->isAlignValT()) { |
| ++NumBaseParams; |
| HasAlignValT = true; |
| } |
| |
| // In CUDA, determine how much we'd like / dislike to call this. |
| if (S.getLangOpts().CUDA) |
| if (auto *Caller = dyn_cast<FunctionDecl>(S.CurContext)) |
| CUDAPref = S.IdentifyCUDAPreference(Caller, FD); |
| } |
| |
| explicit operator bool() const { return FD; } |
| |
| bool isBetterThan(const UsualDeallocFnInfo &Other, bool WantSize, |
| bool WantAlign) const { |
| // C++ P0722: |
| // A destroying operator delete is preferred over a non-destroying |
| // operator delete. |
| if (Destroying != Other.Destroying) |
| return Destroying; |
| |
| // C++17 [expr.delete]p10: |
| // If the type has new-extended alignment, a function with a parameter |
| // of type std::align_val_t is preferred; otherwise a function without |
| // such a parameter is preferred |
| if (HasAlignValT != Other.HasAlignValT) |
| return HasAlignValT == WantAlign; |
| |
| if (HasSizeT != Other.HasSizeT) |
| return HasSizeT == WantSize; |
| |
| // Use CUDA call preference as a tiebreaker. |
| return CUDAPref > Other.CUDAPref; |
| } |
| |
| DeclAccessPair Found; |
| FunctionDecl *FD; |
| bool Destroying, HasSizeT, HasAlignValT; |
| Sema::CUDAFunctionPreference CUDAPref; |
| }; |
| } |
| |
| /// Determine whether a type has new-extended alignment. This may be called when |
| /// the type is incomplete (for a delete-expression with an incomplete pointee |
| /// type), in which case it will conservatively return false if the alignment is |
| /// not known. |
| static bool hasNewExtendedAlignment(Sema &S, QualType AllocType) { |
| return S.getLangOpts().AlignedAllocation && |
| S.getASTContext().getTypeAlignIfKnown(AllocType) > |
| S.getASTContext().getTargetInfo().getNewAlign(); |
| } |
| |
| /// Select the correct "usual" deallocation function to use from a selection of |
| /// deallocation functions (either global or class-scope). |
| static UsualDeallocFnInfo resolveDeallocationOverload( |
| Sema &S, LookupResult &R, bool WantSize, bool WantAlign, |
| llvm::SmallVectorImpl<UsualDeallocFnInfo> *BestFns = nullptr) { |
| UsualDeallocFnInfo Best; |
| |
| for (auto I = R.begin(), E = R.end(); I != E; ++I) { |
| UsualDeallocFnInfo Info(S, I.getPair()); |
| if (!Info || !isNonPlacementDeallocationFunction(S, Info.FD) || |
| Info.CUDAPref == Sema::CFP_Never) |
| continue; |
| |
| if (!Best) { |
| Best = Info; |
| if (BestFns) |
| BestFns->push_back(Info); |
| continue; |
| } |
| |
| if (Best.isBetterThan(Info, WantSize, WantAlign)) |
| continue; |
| |
| // If more than one preferred function is found, all non-preferred |
| // functions are eliminated from further consideration. |
| if (BestFns && Info.isBetterThan(Best, WantSize, WantAlign)) |
| BestFns->clear(); |
| |
| Best = Info; |
| if (BestFns) |
| BestFns->push_back(Info); |
| } |
| |
| return Best; |
| } |
| |
| /// Determine whether a given type is a class for which 'delete[]' would call |
| /// a member 'operator delete[]' with a 'size_t' parameter. This implies that |
| /// we need to store the array size (even if the type is |
| /// trivially-destructible). |
| static bool doesUsualArrayDeleteWantSize(Sema &S, SourceLocation loc, |
| QualType allocType) { |
| const RecordType *record = |
| allocType->getBaseElementTypeUnsafe()->getAs<RecordType>(); |
| if (!record) return false; |
| |
| // Try to find an operator delete[] in class scope. |
| |
| DeclarationName deleteName = |
| S.Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); |
| LookupResult ops(S, deleteName, loc, Sema::LookupOrdinaryName); |
| S.LookupQualifiedName(ops, record->getDecl()); |
| |
| // We're just doing this for information. |
| ops.suppressDiagnostics(); |
| |
| // Very likely: there's no operator delete[]. |
| if (ops.empty()) return false; |
| |
| // If it's ambiguous, it should be illegal to call operator delete[] |
| // on this thing, so it doesn't matter if we allocate extra space or not. |
| if (ops.isAmbiguous()) return false; |
| |
| // C++17 [expr.delete]p10: |
| // If the deallocation functions have class scope, the one without a |
| // parameter of type std::size_t is selected. |
| auto Best = resolveDeallocationOverload( |
| S, ops, /*WantSize*/false, |
| /*WantAlign*/hasNewExtendedAlignment(S, allocType)); |
| return Best && Best.HasSizeT; |
| } |
| |
| /// Parsed a C++ 'new' expression (C++ 5.3.4). |
| /// |
| /// E.g.: |
| /// @code new (memory) int[size][4] @endcode |
| /// or |
| /// @code ::new Foo(23, "hello") @endcode |
| /// |
| /// \param StartLoc The first location of the expression. |
| /// \param UseGlobal True if 'new' was prefixed with '::'. |
| /// \param PlacementLParen Opening paren of the placement arguments. |
| /// \param PlacementArgs Placement new arguments. |
| /// \param PlacementRParen Closing paren of the placement arguments. |
| /// \param TypeIdParens If the type is in parens, the source range. |
| /// \param D The type to be allocated, as well as array dimensions. |
| /// \param Initializer The initializing expression or initializer-list, or null |
| /// if there is none. |
| ExprResult |
| Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, |
| SourceLocation PlacementLParen, MultiExprArg PlacementArgs, |
| SourceLocation PlacementRParen, SourceRange TypeIdParens, |
| Declarator &D, Expr *Initializer) { |
| Optional<Expr *> ArraySize; |
| // If the specified type is an array, unwrap it and save the expression. |
| if (D.getNumTypeObjects() > 0 && |
| D.getTypeObject(0).Kind == DeclaratorChunk::Array) { |
| DeclaratorChunk &Chunk = D.getTypeObject(0); |
| if (D.getDeclSpec().hasAutoTypeSpec()) |
| return ExprError(Diag(Chunk.Loc, diag::err_new_array_of_auto) |
| << D.getSourceRange()); |
| if (Chunk.Arr.hasStatic) |
| return ExprError(Diag(Chunk.Loc, diag::err_static_illegal_in_new) |
| << D.getSourceRange()); |
| if (!Chunk.Arr.NumElts && !Initializer) |
| return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) |
| << D.getSourceRange()); |
| |
| ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); |
| D.DropFirstTypeObject(); |
| } |
| |
| // Every dimension shall be of constant size. |
| if (ArraySize) { |
| for (unsigned I = 0, N = D.getNumTypeObjects(); I < N; ++I) { |
| if (D.getTypeObject(I).Kind != DeclaratorChunk::Array) |
| break; |
| |
| DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; |
| if (Expr *NumElts = (Expr *)Array.NumElts) { |
| if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { |
| if (getLangOpts().CPlusPlus14) { |
| // C++1y [expr.new]p6: Every constant-expression in a noptr-new-declarator |
| // shall be a converted constant expression (5.19) of type std::size_t |
| // and shall evaluate to a strictly positive value. |
| unsigned IntWidth = Context.getTargetInfo().getIntWidth(); |
| assert(IntWidth && "Builtin type of size 0?"); |
| llvm::APSInt Value(IntWidth); |
| Array.NumElts |
| = CheckConvertedConstantExpression(NumElts, Context.getSizeType(), Value, |
| CCEK_NewExpr) |
| .get(); |
| } else { |
| Array.NumElts |
| = VerifyIntegerConstantExpression(NumElts, nullptr, |
| diag::err_new_array_nonconst) |
| .get(); |
| } |
| if (!Array.NumElts) |
| return ExprError(); |
| } |
| } |
| } |
| } |
| |
| TypeSourceInfo *TInfo = GetTypeForDeclarator(D, /*Scope=*/nullptr); |
| QualType AllocType = TInfo->getType(); |
| if (D.isInvalidType()) |
| return ExprError(); |
| |
| SourceRange DirectInitRange; |
| if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) |
| DirectInitRange = List->getSourceRange(); |
| |
| return BuildCXXNew(SourceRange(StartLoc, D.getEndLoc()), UseGlobal, |
| PlacementLParen, PlacementArgs, PlacementRParen, |
| TypeIdParens, AllocType, TInfo, ArraySize, DirectInitRange, |
| Initializer); |
| } |
| |
| static bool isLegalArrayNewInitializer(CXXNewExpr::InitializationStyle Style, |
| Expr *Init) { |
| if (!Init) |
| return true; |
| if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) |
| return PLE->getNumExprs() == 0; |
| if (isa<ImplicitValueInitExpr>(Init)) |
| return true; |
| else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) |
| return !CCE->isListInitialization() && |
| CCE->getConstructor()->isDefaultConstructor(); |
| else if (Style == CXXNewExpr::ListInit) { |
| assert(isa<InitListExpr>(Init) && |
| "Shouldn't create list CXXConstructExprs for arrays."); |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| Sema::isUnavailableAlignedAllocationFunction(const FunctionDecl &FD) const { |
| if (!getLangOpts().AlignedAllocationUnavailable) |
| return false; |
| if (FD.isDefined()) |
| return false; |
| bool IsAligned = false; |
| if (FD.isReplaceableGlobalAllocationFunction(&IsAligned) && IsAligned) |
| return true; |
| return false; |
| } |
| |
| // Emit a diagnostic if an aligned allocation/deallocation function that is not |
| // implemented in the standard library is selected. |
| void Sema::diagnoseUnavailableAlignedAllocation(const FunctionDecl &FD, |
| SourceLocation Loc) { |
| if (isUnavailableAlignedAllocationFunction(FD)) { |
| const llvm::Triple &T = getASTContext().getTargetInfo().getTriple(); |
| StringRef OSName = AvailabilityAttr::getPlatformNameSourceSpelling( |
| getASTContext().getTargetInfo().getPlatformName()); |
| |
| OverloadedOperatorKind Kind = FD.getDeclName().getCXXOverloadedOperator(); |
| bool IsDelete = Kind == OO_Delete || Kind == OO_Array_Delete; |
| Diag(Loc, diag::err_aligned_allocation_unavailable) |
| << IsDelete << FD.getType().getAsString() << OSName |
| << alignedAllocMinVersion(T.getOS()).getAsString(); |
| Diag(Loc, diag::note_silence_aligned_allocation_unavailable); |
| } |
| } |
| |
| ExprResult |
| Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, |
| SourceLocation PlacementLParen, |
| MultiExprArg PlacementArgs, |
| SourceLocation PlacementRParen, |
| SourceRange TypeIdParens, |
| QualType AllocType, |
| TypeSourceInfo *AllocTypeInfo, |
| Optional<Expr *> ArraySize, |
| SourceRange DirectInitRange, |
| Expr *Initializer) { |
| SourceRange TypeRange = AllocTypeInfo->getTypeLoc().getSourceRange(); |
| SourceLocation StartLoc = Range.getBegin(); |
| |
| CXXNewExpr::InitializationStyle initStyle; |
| if (DirectInitRange.isValid()) { |
| assert(Initializer && "Have parens but no initializer."); |
| initStyle = CXXNewExpr::CallInit; |
| } else if (Initializer && isa<InitListExpr>(Initializer)) |
| initStyle = CXXNewExpr::ListInit; |
| else { |
| assert((!Initializer || isa<ImplicitValueInitExpr>(Initializer) || |
| isa<CXXConstructExpr>(Initializer)) && |
| "Initializer expression that cannot have been implicitly created."); |
| initStyle = CXXNewExpr::NoInit; |
| } |
| |
| Expr **Inits = &Initializer; |
| unsigned NumInits = Initializer ? 1 : 0; |
| if (ParenListExpr *List = dyn_cast_or_null<ParenListExpr>(Initializer)) { |
| assert(initStyle == CXXNewExpr::CallInit && "paren init for non-call init"); |
| Inits = List->getExprs(); |
| NumInits = List->getNumExprs(); |
| } |
| |
| // C++11 [expr.new]p15: |
| // A new-expression that creates an object of type T initializes that |
| // object as follows: |
| InitializationKind Kind |
| // - If the new-initializer is omitted, the object is default- |
| // initialized (8.5); if no initialization is performed, |
| // the object has indeterminate value |
| = initStyle == CXXNewExpr::NoInit |
| ? InitializationKind::CreateDefault(TypeRange.getBegin()) |
| // - Otherwise, the new-initializer is interpreted according to |
| // the |
| // initialization rules of 8.5 for direct-initialization. |
| : initStyle == CXXNewExpr::ListInit |
| ? InitializationKind::CreateDirectList( |
| TypeRange.getBegin(), Initializer->getBeginLoc(), |
| Initializer->getEndLoc()) |
| : InitializationKind::CreateDirect(TypeRange.getBegin(), |
| DirectInitRange.getBegin(), |
| DirectInitRange.getEnd()); |
| |
| // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. |
| auto *Deduced = AllocType->getContainedDeducedType(); |
| if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { |
| if (ArraySize) |
| return ExprError( |
| Diag(ArraySize ? (*ArraySize)->getExprLoc() : TypeRange.getBegin(), |
| diag::err_deduced_class_template_compound_type) |
| << /*array*/ 2 |
| << (ArraySize ? (*ArraySize)->getSourceRange() : TypeRange)); |
| |
| InitializedEntity Entity |
| = InitializedEntity::InitializeNew(StartLoc, AllocType); |
| AllocType = DeduceTemplateSpecializationFromInitializer( |
| AllocTypeInfo, Entity, Kind, MultiExprArg(Inits, NumInits)); |
| if (AllocType.isNull()) |
| return ExprError(); |
| } else if (Deduced) { |
| bool Braced = (initStyle == CXXNewExpr::ListInit); |
| if (NumInits == 1) { |
| if (auto p = dyn_cast_or_null<InitListExpr>(Inits[0])) { |
| Inits = p->getInits(); |
| NumInits = p->getNumInits(); |
| Braced = true; |
| } |
| } |
| |
| if (initStyle == CXXNewExpr::NoInit || NumInits == 0) |
| return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) |
| << AllocType << TypeRange); |
| if (NumInits > 1) { |
| Expr *FirstBad = Inits[1]; |
| return ExprError(Diag(FirstBad->getBeginLoc(), |
| diag::err_auto_new_ctor_multiple_expressions) |
| << AllocType << TypeRange); |
| } |
| if (Braced && !getLangOpts().CPlusPlus17) |
| Diag(Initializer->getBeginLoc(), diag::ext_auto_new_list_init) |
| << AllocType << TypeRange; |
| Expr *Deduce = Inits[0]; |
| QualType DeducedType; |
| if (DeduceAutoType(AllocTypeInfo, Deduce, DeducedType) == DAR_Failed) |
| return ExprError(Diag(StartLoc, diag::err_auto_new_deduction_failure) |
| << AllocType << Deduce->getType() |
| << TypeRange << Deduce->getSourceRange()); |
| if (DeducedType.isNull()) |
| return ExprError(); |
| AllocType = DeducedType; |
| } |
| |
| // Per C++0x [expr.new]p5, the type being constructed may be a |
| // typedef of an array type. |
| if (!ArraySize) { |
| if (const ConstantArrayType *Array |
| = Context.getAsConstantArrayType(AllocType)) { |
| ArraySize = IntegerLiteral::Create(Context, Array->getSize(), |
| Context.getSizeType(), |
| TypeRange.getEnd()); |
| AllocType = Array->getElementType(); |
| } |
| } |
| |
| if (CheckAllocatedType(AllocType, TypeRange.getBegin(), TypeRange)) |
| return ExprError(); |
| |
| // In ARC, infer 'retaining' for the allocated |
| if (getLangOpts().ObjCAutoRefCount && |
| AllocType.getObjCLifetime() == Qualifiers::OCL_None && |
| AllocType->isObjCLifetimeType()) { |
| AllocType = Context.getLifetimeQualifiedType(AllocType, |
| AllocType->getObjCARCImplicitLifetime()); |
| } |
| |
| QualType ResultType = Context.getPointerType(AllocType); |
| |
| if (ArraySize && *ArraySize && |
| (*ArraySize)->getType()->isNonOverloadPlaceholderType()) { |
| ExprResult result = CheckPlaceholderExpr(*ArraySize); |
| if (result.isInvalid()) return ExprError(); |
| ArraySize = result.get(); |
| } |
| // C++98 5.3.4p6: "The expression in a direct-new-declarator shall have |
| // integral or enumeration type with a non-negative value." |
| // C++11 [expr.new]p6: The expression [...] shall be of integral or unscoped |
| // enumeration type, or a class type for which a single non-explicit |
| // conversion function to integral or unscoped enumeration type exists. |
| // C++1y [expr.new]p6: The expression [...] is implicitly converted to |
| // std::size_t. |
| llvm::Optional<uint64_t> KnownArraySize; |
| if (ArraySize && *ArraySize && !(*ArraySize)->isTypeDependent()) { |
| ExprResult ConvertedSize; |
| if (getLangOpts().CPlusPlus14) { |
| assert(Context.getTargetInfo().getIntWidth() && "Builtin type of size 0?"); |
| |
| ConvertedSize = PerformImplicitConversion(*ArraySize, Context.getSizeType(), |
| AA_Converting); |
| |
| if (!ConvertedSize.isInvalid() && |
| (*ArraySize)->getType()->getAs<RecordType>()) |
| // Diagnose the compatibility of this conversion. |
| Diag(StartLoc, diag::warn_cxx98_compat_array_size_conversion) |
| << (*ArraySize)->getType() << 0 << "'size_t'"; |
| } else { |
| class SizeConvertDiagnoser : public ICEConvertDiagnoser { |
| protected: |
| Expr *ArraySize; |
| |
| public: |
| SizeConvertDiagnoser(Expr *ArraySize) |
| : ICEConvertDiagnoser(/*AllowScopedEnumerations*/false, false, false), |
| ArraySize(ArraySize) {} |
| |
| SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, |
| QualType T) override { |
| return S.Diag(Loc, diag::err_array_size_not_integral) |
| << S.getLangOpts().CPlusPlus11 << T; |
| } |
| |
| SemaDiagnosticBuilder diagnoseIncomplete( |
| Sema &S, SourceLocation Loc, QualType T) override { |
| return S.Diag(Loc, diag::err_array_size_incomplete_type) |
| << T << ArraySize->getSourceRange(); |
| } |
| |
| SemaDiagnosticBuilder diagnoseExplicitConv( |
| Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) override { |
| return S.Diag(Loc, diag::err_array_size_explicit_conversion) << T << ConvTy; |
| } |
| |
| SemaDiagnosticBuilder noteExplicitConv( |
| Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { |
| return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) |
| << ConvTy->isEnumeralType() << ConvTy; |
| } |
| |
| SemaDiagnosticBuilder diagnoseAmbiguous( |
| Sema &S, SourceLocation Loc, QualType T) override { |
| return S.Diag(Loc, diag::err_array_size_ambiguous_conversion) << T; |
| } |
| |
| SemaDiagnosticBuilder noteAmbiguous( |
| Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { |
| return S.Diag(Conv->getLocation(), diag::note_array_size_conversion) |
| << ConvTy->isEnumeralType() << ConvTy; |
| } |
| |
| SemaDiagnosticBuilder diagnoseConversion(Sema &S, SourceLocation Loc, |
| QualType T, |
| QualType ConvTy) override { |
| return S.Diag(Loc, |
| S.getLangOpts().CPlusPlus11 |
| ? diag::warn_cxx98_compat_array_size_conversion |
| : diag::ext_array_size_conversion) |
| << T << ConvTy->isEnumeralType() << ConvTy; |
| } |
| } SizeDiagnoser(*ArraySize); |
| |
| ConvertedSize = PerformContextualImplicitConversion(StartLoc, *ArraySize, |
| SizeDiagnoser); |
| } |
| if (ConvertedSize.isInvalid()) |
| return ExprError(); |
| |
| ArraySize = ConvertedSize.get(); |
| QualType SizeType = (*ArraySize)->getType(); |
| |
| if (!SizeType->isIntegralOrUnscopedEnumerationType()) |
| return ExprError(); |
| |
| // C++98 [expr.new]p7: |
| // The expression in a direct-new-declarator shall have integral type |
| // with a non-negative value. |
| // |
| // Let's see if this is a constant < 0. If so, we reject it out of hand, |
| // per CWG1464. Otherwise, if it's not a constant, we must have an |
| // unparenthesized array type. |
| if (!(*ArraySize)->isValueDependent()) { |
| llvm::APSInt Value; |
| // We've already performed any required implicit conversion to integer or |
| // unscoped enumeration type. |
| // FIXME: Per CWG1464, we are required to check the value prior to |
| // converting to size_t. This will never find a negative array size in |
| // C++14 onwards, because Value is always unsigned here! |
| if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) { |
| if (Value.isSigned() && Value.isNegative()) { |
| return ExprError(Diag((*ArraySize)->getBeginLoc(), |
| diag::err_typecheck_negative_array_size) |
| << (*ArraySize)->getSourceRange()); |
| } |
| |
| if (!AllocType->isDependentType()) { |
| unsigned ActiveSizeBits = |
| ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); |
| if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) |
| return ExprError( |
| Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large) |
| << Value.toString(10) << (*ArraySize)->getSourceRange()); |
| } |
| |
| KnownArraySize = Value.getZExtValue(); |
| } else if (TypeIdParens.isValid()) { |
| // Can't have dynamic array size when the type-id is in parentheses. |
| Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst) |
| << (*ArraySize)->getSourceRange() |
| << FixItHint::CreateRemoval(TypeIdParens.getBegin()) |
| << FixItHint::CreateRemoval(TypeIdParens.getEnd()); |
| |
| TypeIdParens = SourceRange(); |
| } |
| } |
| |
| // Note that we do *not* convert the argument in any way. It can |
| // be signed, larger than size_t, whatever. |
| } |
| |
| FunctionDecl *OperatorNew = nullptr; |
| FunctionDecl *OperatorDelete = nullptr; |
| unsigned Alignment = |
| AllocType->isDependentType() ? 0 : Context.getTypeAlign(AllocType); |
| unsigned NewAlignment = Context.getTargetInfo().getNewAlign(); |
| bool PassAlignment = getLangOpts().AlignedAllocation && |
| Alignment > NewAlignment; |
| |
| AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both; |
| if (!AllocType->isDependentType() && |
| !Expr::hasAnyTypeDependentArguments(PlacementArgs) && |
| FindAllocationFunctions( |
| StartLoc, SourceRange(PlacementLParen, PlacementRParen), Scope, Scope, |
| AllocType, ArraySize.hasValue(), PassAlignment, PlacementArgs, |
| OperatorNew, OperatorDelete)) |
| return ExprError(); |
| |
| // If this is an array allocation, compute whether the usual array |
| // deallocation function for the type has a size_t parameter. |
| bool UsualArrayDeleteWantsSize = false; |
| if (ArraySize && !AllocType->isDependentType()) |
| UsualArrayDeleteWantsSize = |
| doesUsualArrayDeleteWantSize(*this, StartLoc, AllocType); |
| |
| SmallVector<Expr *, 8> AllPlaceArgs; |
| if (OperatorNew) { |
| const FunctionProtoType *Proto = |
| OperatorNew->getType()->getAs<FunctionProtoType>(); |
| VariadicCallType CallType = Proto->isVariadic() ? VariadicFunction |
| : VariadicDoesNotApply; |
| |
| // We've already converted the placement args, just fill in any default |
| // arguments. Skip the first parameter because we don't have a corresponding |
| // argument. Skip the second parameter too if we're passing in the |
| // alignment; we've already filled it in. |
| if (GatherArgumentsForCall(PlacementLParen, OperatorNew, Proto, |
| PassAlignment ? 2 : 1, PlacementArgs, |
| AllPlaceArgs, CallType)) |
| return ExprError(); |
| |
| if (!AllPlaceArgs.empty()) |
| PlacementArgs = AllPlaceArgs; |
| |
| // FIXME: This is wrong: PlacementArgs misses out the first (size) argument. |
| DiagnoseSentinelCalls(OperatorNew, PlacementLParen, PlacementArgs); |
| |
| // FIXME: Missing call to CheckFunctionCall or equivalent |
| |
| // Warn if the type is over-aligned and is being allocated by (unaligned) |
| // global operator new. |
| if (PlacementArgs.empty() && !PassAlignment && |
| (OperatorNew->isImplicit() || |
| (OperatorNew->getBeginLoc().isValid() && |
| getSourceManager().isInSystemHeader(OperatorNew->getBeginLoc())))) { |
| if (Alignment > NewAlignment) |
| Diag(StartLoc, diag::warn_overaligned_type) |
| << AllocType |
| << unsigned(Alignment / Context.getCharWidth()) |
| << unsigned(NewAlignment / Context.getCharWidth()); |
| } |
| } |
| |
| // Array 'new' can't have any initializers except empty parentheses. |
| // Initializer lists are also allowed, in C++11. Rely on the parser for the |
| // dialect distinction. |
| if (ArraySize && !isLegalArrayNewInitializer(initStyle, Initializer)) { |
| SourceRange InitRange(Inits[0]->getBeginLoc(), |
| Inits[NumInits - 1]->getEndLoc()); |
| Diag(StartLoc, diag::err_new_array_init_args) << InitRange; |
| return ExprError(); |
| } |
| |
| // If we can perform the initialization, and we've not already done so, |
| // do it now. |
| if (!AllocType->isDependentType() && |
| !Expr::hasAnyTypeDependentArguments( |
| llvm::makeArrayRef(Inits, NumInits))) { |
| // The type we initialize is the complete type, including the array bound. |
| QualType InitType; |
| if (KnownArraySize) |
| InitType = Context.getConstantArrayType( |
| AllocType, |
| llvm::APInt(Context.getTypeSize(Context.getSizeType()), |
| *KnownArraySize), |
| *ArraySize, ArrayType::Normal, 0); |
| else if (ArraySize) |
| InitType = |
| Context.getIncompleteArrayType(AllocType, ArrayType::Normal, 0); |
| else |
| InitType = AllocType; |
| |
| InitializedEntity Entity |
| = InitializedEntity::InitializeNew(StartLoc, InitType); |
| InitializationSequence InitSeq(*this, Entity, Kind, |
| MultiExprArg(Inits, NumInits)); |
| ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, |
| MultiExprArg(Inits, NumInits)); |
| if (FullInit.isInvalid()) |
| return ExprError(); |
| |
| // FullInit is our initializer; strip off CXXBindTemporaryExprs, because |
| // we don't want the initialized object to be destructed. |
| // FIXME: We should not create these in the first place. |
| if (CXXBindTemporaryExpr *Binder = |
| dyn_cast_or_null<CXXBindTemporaryExpr>(FullInit.get())) |
| FullInit = Binder->getSubExpr(); |
| |
| Initializer = FullInit.get(); |
| |
| // FIXME: If we have a KnownArraySize, check that the array bound of the |
| // initializer is no greater than that constant value. |
| |
| if (ArraySize && !*ArraySize) { |
| auto *CAT = Context.getAsConstantArrayType(Initializer->getType()); |
| if (CAT) { |
| // FIXME: Track that the array size was inferred rather than explicitly |
| // specified. |
| ArraySize = IntegerLiteral::Create( |
| Context, CAT->getSize(), Context.getSizeType(), TypeRange.getEnd()); |
| } else { |
| Diag(TypeRange.getEnd(), diag::err_new_array_size_unknown_from_init) |
| << Initializer->getSourceRange(); |
| } |
| } |
| } |
| |
| // Mark the new and delete operators as referenced. |
| if (OperatorNew) { |
| if (DiagnoseUseOfDecl(OperatorNew, StartLoc)) |
| return ExprError(); |
| MarkFunctionReferenced(StartLoc, OperatorNew); |
| } |
| if (OperatorDelete) { |
| if (DiagnoseUseOfDecl(OperatorDelete, StartLoc)) |
| return ExprError(); |
| MarkFunctionReferenced(StartLoc, OperatorDelete); |
| } |
| |
| return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete, |
| PassAlignment, UsualArrayDeleteWantsSize, |
| PlacementArgs, TypeIdParens, ArraySize, initStyle, |
| Initializer, ResultType, AllocTypeInfo, Range, |
| DirectInitRange); |
| } |
| |
| /// Checks that a type is suitable as the allocated type |
| /// in a new-expression. |
| bool Sema::CheckAllocatedType(QualType AllocType, SourceLocation Loc, |
| SourceRange R) { |
| // C++ 5.3.4p1: "[The] type shall be a complete object type, but not an |
| // abstract class type or array thereof. |
| if (AllocType->isFunctionType()) |
| return Diag(Loc, diag::err_bad_new_type) |
| << AllocType << 0 << R; |
| else if (AllocType->isReferenceType()) |
| return Diag(Loc, diag::err_bad_new_type) |
| << AllocType << 1 << R; |
| else if (!AllocType->isDependentType() && |
| RequireCompleteType(Loc, AllocType, diag::err_new_incomplete_type,R)) |
| return true; |
| else if (RequireNonAbstractType(Loc, AllocType, |
| diag::err_allocation_of_abstract_type)) |
| return true; |
| else if (AllocType->isVariablyModifiedType()) |
| return Diag(Loc, diag::err_variably_modified_new_type) |
| << AllocType; |
| else if (AllocType.getAddressSpace() != LangAS::Default && |
| !getLangOpts().OpenCLCPlusPlus) |
| return Diag(Loc, diag::err_address_space_qualified_new) |
| << AllocType.getUnqualifiedType() |
| << AllocType.getQualifiers().getAddressSpaceAttributePrintValue(); |
| else if (getLangOpts().ObjCAutoRefCount) { |
| if (const ArrayType *AT = Context.getAsArrayType(AllocType)) { |
| QualType BaseAllocType = Context.getBaseElementType(AT); |
| if (BaseAllocType.getObjCLifetime() == Qualifiers::OCL_None && |
| BaseAllocType->isObjCLifetimeType()) |
| return Diag(Loc, diag::err_arc_new_array_without_ownership) |
| << BaseAllocType; |
| } |
| } |
| |
| return false; |
| } |
| |
| static bool resolveAllocationOverload( |
| Sema &S, LookupResult &R, SourceRange Range, SmallVectorImpl<Expr *> &Args, |
| bool &PassAlignment, FunctionDecl *&Operator, |
| OverloadCandidateSet *AlignedCandidates, Expr *AlignArg, bool Diagnose) { |
| OverloadCandidateSet Candidates(R.getNameLoc(), |
| OverloadCandidateSet::CSK_Normal); |
| for (LookupResult::iterator Alloc = R.begin(), AllocEnd = R.end(); |
| Alloc != AllocEnd; ++Alloc) { |
| // Even member operator new/delete are implicitly treated as |
| // static, so don't use AddMemberCandidate. |
| NamedDecl *D = (*Alloc)->getUnderlyingDecl(); |
| |
| if (FunctionTemplateDecl *FnTemplate = dyn_cast<FunctionTemplateDecl>(D)) { |
| S.AddTemplateOverloadCandidate(FnTemplate, Alloc.getPair(), |
| /*ExplicitTemplateArgs=*/nullptr, Args, |
| Candidates, |
| /*SuppressUserConversions=*/false); |
| continue; |
| } |
| |
| FunctionDecl *Fn = cast<FunctionDecl>(D); |
| S.AddOverloadCandidate(Fn, Alloc.getPair(), Args, Candidates, |
| /*SuppressUserConversions=*/false); |
| } |
| |
| // Do the resolution. |
| OverloadCandidateSet::iterator Best; |
| switch (Candidates.BestViableFunction(S, R.getNameLoc(), Best)) { |
| case OR_Success: { |
| // Got one! |
| FunctionDecl *FnDecl = Best->Function; |
| if (S.CheckAllocationAccess(R.getNameLoc(), Range, R.getNamingClass(), |
| Best->FoundDecl) == Sema::AR_inaccessible) |
| return true; |
| |
| Operator = FnDecl; |
| return false; |
| } |
| |
| case OR_No_Viable_Function: |
| // C++17 [expr.new]p13: |
| // If no matching function is found and the allocated object type has |
| // new-extended alignment, the alignment argument is removed from the |
| // argument list, and overload resolution is performed again. |
| if (PassAlignment) { |
| PassAlignment = false; |
| AlignArg = Args[1]; |
| Args.erase(Args.begin() + 1); |
| return resolveAllocationOverload(S, R, Range, Args, PassAlignment, |
| Operator, &Candidates, AlignArg, |
| Diagnose); |
| } |
| |
| // MSVC will fall back on trying to find a matching global operator new |
| // if operator new[] cannot be found. Also, MSVC will leak by not |
| // generating a call to operator delete or operator delete[], but we |
| // will not replicate that bug. |
| // FIXME: Find out how this interacts with the std::align_val_t fallback |
| // once MSVC implements it. |
| if (R.getLookupName().getCXXOverloadedOperator() == OO_Array_New && |
| S.Context.getLangOpts().MSVCCompat) { |
| R.clear(); |
| R.setLookupName(S.Context.DeclarationNames.getCXXOperatorName(OO_New)); |
| S.LookupQualifiedName(R, S.Context.getTranslationUnitDecl()); |
| // FIXME: This will give bad diagnostics pointing at the wrong functions. |
| return resolveAllocationOverload(S, R, Range, Args, PassAlignment, |
| Operator, /*Candidates=*/nullptr, |
| /*AlignArg=*/nullptr, Diagnose); |
| } |
| |
| if (Diagnose) { |
| PartialDiagnosticAt PD(R.getNameLoc(), S.PDiag(diag::err_ovl_no_viable_function_in_call) |
| << R.getLookupName() << Range); |
| |
| // If we have aligned candidates, only note the align_val_t candidates |
| // from AlignedCandidates and the non-align_val_t candidates from |
| // Candidates. |
| if (AlignedCandidates) { |
| auto IsAligned = [](OverloadCandidate &C) { |
| return C.Function->getNumParams() > 1 && |
| C.Function->getParamDecl(1)->getType()->isAlignValT(); |
| }; |
| auto IsUnaligned = [&](OverloadCandidate &C) { return !IsAligned(C); }; |
| |
| // This was an overaligned allocation, so list the aligned candidates |
| // first. |
| Args.insert(Args.begin() + 1, AlignArg); |
| AlignedCandidates->NoteCandidates(PD, S, OCD_AllCandidates, Args, "", |
| R.getNameLoc(), IsAligned); |
| Args.erase(Args.begin() + 1); |
| Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args, "", R.getNameLoc(), |
| IsUnaligned); |
| } else { |
| Candidates.NoteCandidates(PD, S, OCD_AllCandidates, Args); |
| } |
| } |
| return true; |
| |
| case OR_Ambiguous: |
| if (Diagnose) { |
| Candidates.NoteCandidates( |
| PartialDiagnosticAt(R.getNameLoc(), |
| S.PDiag(diag::err_ovl_ambiguous_call) |
| << R.getLookupName() << Range), |
| S, OCD_ViableCandidates, Args); |
| } |
| return true; |
| |
| case OR_Deleted: { |
| if (Diagnose) { |
| Candidates.NoteCandidates( |
| PartialDiagnosticAt(R.getNameLoc(), |
| S.PDiag(diag::err_ovl_deleted_call) |
| << R.getLookupName() << Range), |
| S, OCD_AllCandidates, Args); |
| } |
| return true; |
| } |
| } |
| llvm_unreachable("Unreachable, bad result from BestViableFunction"); |
| } |
| |
| bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, |
| AllocationFunctionScope NewScope, |
| AllocationFunctionScope DeleteScope, |
| QualType AllocType, bool IsArray, |
| bool &PassAlignment, MultiExprArg PlaceArgs, |
| FunctionDecl *&OperatorNew, |
| FunctionDecl *&OperatorDelete, |
| bool Diagnose) { |
| // --- Choosing an allocation function --- |
| // C++ 5.3.4p8 - 14 & 18 |
| // 1) If looking in AFS_Global scope for allocation functions, only look in |
| // the global scope. Else, if AFS_Class, only look in the scope of the |
| // allocated class. If AFS_Both, look in both. |
| // 2) If an array size is given, look for operator new[], else look for |
| // operator new. |
| // 3) The first argument is always size_t. Append the arguments from the |
| // placement form. |
| |
| SmallVector<Expr*, 8> AllocArgs; |
| AllocArgs.reserve((PassAlignment ? 2 : 1) + PlaceArgs.size()); |
| |
| // We don't care about the actual value of these arguments. |
| // FIXME: Should the Sema create the expression and embed it in the syntax |
| // tree? Or should the consumer just recalculate the value? |
| // FIXME: Using a dummy value will interact poorly with attribute enable_if. |
| IntegerLiteral Size(Context, llvm::APInt::getNullValue( |
| Context.getTargetInfo().getPointerWidth(0)), |
| Context.getSizeType(), |
| SourceLocation()); |
| AllocArgs.push_back(&Size); |
| |
| QualType AlignValT = Context.VoidTy; |
| if (PassAlignment) { |
| DeclareGlobalNewDelete(); |
| AlignValT = Context.getTypeDeclType(getStdAlignValT()); |
| } |
| CXXScalarValueInitExpr Align(AlignValT, nullptr, SourceLocation()); |
| if (PassAlignment) |
| AllocArgs.push_back(&Align); |
| |
| AllocArgs.insert(AllocArgs.end(), PlaceArgs.begin(), PlaceArgs.end()); |
| |
| // C++ [expr.new]p8: |
| // If the allocated type is a non-array type, the allocation |
| // function's name is operator new and the deallocation function's |
| // name is operator delete. If the allocated type is an array |
| // type, the allocation function's name is operator new[] and the |
| // deallocation function's name is operator delete[]. |
| DeclarationName NewName = Context.DeclarationNames.getCXXOperatorName( |
| IsArray ? OO_Array_New : OO_New); |
| |
| QualType AllocElemType = Context.getBaseElementType(AllocType); |
| |
| // Find the allocation function. |
| { |
| LookupResult R(*this, NewName, StartLoc, LookupOrdinaryName); |
| |
| // C++1z [expr.new]p9: |
| // If the new-expression begins with a unary :: operator, the allocation |
| // function's name is looked up in the global scope. Otherwise, if the |
| // allocated type is a class type T or array thereof, the allocation |
| // function's name is looked up in the scope of T. |
| if (AllocElemType->isRecordType() && NewScope != AFS_Global) |
| LookupQualifiedName(R, AllocElemType->getAsCXXRecordDecl()); |
| |
| // We can see ambiguity here if the allocation function is found in |
| // multiple base classes. |
| if (R.isAmbiguous()) |
| return true; |
| |
| // If this lookup fails to find the name, or if the allocated type is not |
| // a class type, the allocation function's name is looked up in the |
| // global scope. |
| if (R.empty()) { |
| if (NewScope == AFS_Class) |
| return true; |
| |
| LookupQualifiedName(R, Context.getTranslationUnitDecl()); |
| } |
| |
| if (getLangOpts().OpenCLCPlusPlus && R.empty()) { |
| if (PlaceArgs.empty()) { |
| Diag(StartLoc, diag::err_openclcxx_not_supported) << "default new"; |
| } else { |
| Diag(StartLoc, diag::err_openclcxx_placement_new); |
| } |
| return true; |
| } |
| |
| assert(!R.empty() && "implicitly declared allocation functions not found"); |
| assert(!R.isAmbiguous() && "global allocation functions are ambiguous"); |
| |
| // We do our own custom access checks below. |
| R.suppressDiagnostics(); |
| |
| if (resolveAllocationOverload(*this, R, Range, AllocArgs, PassAlignment, |
| OperatorNew, /*Candidates=*/nullptr, |
| /*AlignArg=*/nullptr, Diagnose)) |
| return true; |
| } |
| |
| // We don't need an operator delete if we're running under -fno-exceptions. |
| if (!getLangOpts().Exceptions) { |
| OperatorDelete = nullptr; |
| return false; |
| } |
| |
| // Note, the name of OperatorNew might have been changed from array to |
| // non-array by resolveAllocationOverload. |
| DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName( |
| OperatorNew->getDeclName().getCXXOverloadedOperator() == OO_Array_New |
| ? OO_Array_Delete |
| : OO_Delete); |
| |
| // C++ [expr.new]p19: |
| // |
| // If the new-expression begins with a unary :: operator, the |
| // deallocation function's name is looked up in the global |
| // scope. Otherwise, if the allocated type is a class type T or an |
| // array thereof, the deallocation function's name is looked up in |
| // the scope of T. If this lookup fails to find the name, or if |
| // the allocated type is not a class type or array thereof, the |
| // deallocation function's name is looked up in the global scope. |
| LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); |
| if (AllocElemType->isRecordType() && DeleteScope != AFS_Global) { |
| auto *RD = |
| cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl()); |
| LookupQualifiedName(FoundDelete, RD); |
| } |
| if (FoundDelete.isAmbiguous()) |
| return true; // FIXME: clean up expressions? |
| |
| bool FoundGlobalDelete = FoundDelete.empty(); |
| if (FoundDelete.empty()) { |
| if (DeleteScope == AFS_Class) |
| return true; |
| |
| DeclareGlobalNewDelete(); |
| LookupQualifiedName(FoundDelete, Context.getTranslationUnitDecl()); |
| } |
| |
| FoundDelete.suppressDiagnostics(); |
| |
| SmallVector<std::pair<DeclAccessPair,FunctionDecl*>, 2> Matches; |
| |
| // Whether we're looking for a placement operator delete is dictated |
| // by whether we selected a placement operator new, not by whether |
| // we had explicit placement arguments. This matters for things like |
| // struct A { void *operator new(size_t, int = 0); ... }; |
| // A *a = new A() |
| // |
| // We don't have any definition for what a "placement allocation function" |
| // is, but we assume it's any allocation function whose |
| // parameter-declaration-clause is anything other than (size_t). |
| // |
| // FIXME: Should (size_t, std::align_val_t) also be considered non-placement? |
| // This affects whether an exception from the constructor of an overaligned |
| // type uses the sized or non-sized form of aligned operator delete. |
| bool isPlacementNew = !PlaceArgs.empty() || OperatorNew->param_size() != 1 || |
| OperatorNew->isVariadic(); |
| |
| if (isPlacementNew) { |
| // C++ [expr.new]p20: |
| // A declaration of a placement deallocation function matches the |
| // declaration of a placement allocation function if it has the |
| // same number of parameters and, after parameter transformations |
| // (8.3.5), all parameter types except the first are |
| // identical. [...] |
| // |
| // To perform this comparison, we compute the function type that |
| // the deallocation function should have, and use that type both |
| // for template argument deduction and for comparison purposes. |
| QualType ExpectedFunctionType; |
| { |
| const FunctionProtoType *Proto |
| = OperatorNew->getType()->getAs<FunctionProtoType>(); |
| |
| SmallVector<QualType, 4> ArgTypes; |
| ArgTypes.push_back(Context.VoidPtrTy); |
| for (unsigned I = 1, N = Proto->getNumParams(); I < N; ++I) |
| ArgTypes.push_back(Proto->getParamType(I)); |
| |
| FunctionProtoType::ExtProtoInfo EPI; |
| // FIXME: This is not part of the standard's rule. |
| EPI.Variadic = Proto->isVariadic(); |
| |
| ExpectedFunctionType |
| = Context.getFunctionType(Context.VoidTy, ArgTypes, EPI); |
| } |
| |
| for (LookupResult::iterator D = FoundDelete.begin(), |
| DEnd = FoundDelete.end(); |
| D != DEnd; ++D) { |
| FunctionDecl *Fn = nullptr; |
| if (FunctionTemplateDecl *FnTmpl = |
| dyn_cast<FunctionTemplateDecl>((*D)->getUnderlyingDecl())) { |
| // Perform template argument deduction to try to match the |
| // expected function type. |
| TemplateDeductionInfo Info(StartLoc); |
| if (DeduceTemplateArguments(FnTmpl, nullptr, ExpectedFunctionType, Fn, |
| Info)) |
| continue; |
| } else |
| Fn = cast<FunctionDecl>((*D)->getUnderlyingDecl()); |
| |
| if (Context.hasSameType(adjustCCAndNoReturn(Fn->getType(), |
| ExpectedFunctionType, |
| /*AdjustExcpetionSpec*/true), |
| ExpectedFunctionType)) |
| Matches.push_back(std::make_pair(D.getPair(), Fn)); |
| } |
| |
| if (getLangOpts().CUDA) |
| EraseUnwantedCUDAMatches(dyn_cast<FunctionDecl>(CurContext), Matches); |
| } else { |
| // C++1y [expr.new]p22: |
| // For a non-placement allocation function, the normal deallocation |
| // function lookup is used |
| // |
| // Per [expr.delete]p10, this lookup prefers a member operator delete |
| // without a size_t argument, but prefers a non-member operator delete |
| // with a size_t where possible (which it always is in this case). |
| llvm::SmallVector<UsualDeallocFnInfo, 4> BestDeallocFns; |
| UsualDeallocFnInfo Selected = resolveDeallocationOverload( |
| *this, FoundDelete, /*WantSize*/ FoundGlobalDelete, |
| /*WantAlign*/ hasNewExtendedAlignment(*this, AllocElemType), |
| &BestDeallocFns); |
| if (Selected) |
| Matches.push_back(std::make_pair(Selected.Found, Selected.FD)); |
| else { |
| // If we failed to select an operator, all remaining functions are viable |
| // but ambiguous. |
| for (auto Fn : BestDeallocFns) |
| Matches.push_back(std::make_pair(Fn.Found, Fn.FD)); |
| } |
| } |
| |
| // C++ [expr.new]p20: |
| // [...] If the lookup finds a single matching deallocation |
| // function, that function will be called; otherwise, no |
| // deallocation function will be called. |
| if (Matches.size() == 1) { |
| OperatorDelete = Matches[0].second; |
| |
| // C++1z [expr.new]p23: |
| // If the lookup finds a usual deallocation function (3.7.4.2) |
| // with a parameter of type std::size_t and that function, considered |
| // as a placement deallocation function, would have been |
| // selected as a match for the allocation function, the program |
| // is ill-formed. |
| if (getLangOpts().CPlusPlus11 && isPlacementNew && |
| isNonPlacementDeallocationFunction(*this, OperatorDelete)) { |
| UsualDeallocFnInfo Info(*this, |
| DeclAccessPair::make(OperatorDelete, AS_public)); |
| // Core issue, per mail to core reflector, 2016-10-09: |
| // If this is a member operator delete, and there is a corresponding |
| // non-sized member operator delete, this isn't /really/ a sized |
| // deallocation function, it just happens to have a size_t parameter. |
| bool IsSizedDelete = Info.HasSizeT; |
| if (IsSizedDelete && !FoundGlobalDelete) { |
| auto NonSizedDelete = |
| resolveDeallocationOverload(*this, FoundDelete, /*WantSize*/false, |
| /*WantAlign*/Info.HasAlignValT); |
| if (NonSizedDelete && !NonSizedDelete.HasSizeT && |
| NonSizedDelete.HasAlignValT == Info.HasAlignValT) |
| IsSizedDelete = false; |
| } |
| |
| if (IsSizedDelete) { |
| SourceRange R = PlaceArgs.empty() |
| ? SourceRange() |
| : SourceRange(PlaceArgs.front()->getBeginLoc(), |
| PlaceArgs.back()->getEndLoc()); |
| Diag(StartLoc, diag::err_placement_new_non_placement_delete) << R; |
| if (!OperatorDelete->isImplicit()) |
| Diag(OperatorDelete->getLocation(), diag::note_previous_decl) |
| << DeleteName; |
| } |
| } |
| |
| CheckAllocationAccess(StartLoc, Range, FoundDelete.getNamingClass(), |
| Matches[0].first); |
| } else if (!Matches.empty()) { |
| // We found multiple suitable operators. Per [expr.new]p20, that means we |
| // call no 'operator delete' function, but we should at least warn the user. |
| // FIXME: Suppress this warning if the construction cannot throw. |
| Diag(StartLoc, diag::warn_ambiguous_suitable_delete_function_found) |
| << DeleteName << AllocElemType; |
| |
| for (auto &Match : Matches) |
| Diag(Match.second->getLocation(), |
| diag::note_member_declared_here) << DeleteName; |
| } |
| |
| return false; |
| } |
| |
| /// DeclareGlobalNewDelete - Declare the global forms of operator new and |
| /// delete. These are: |
| /// @code |
| /// // C++03: |
| /// void* operator new(std::size_t) throw(std::bad_alloc); |
| /// void* operator new[](std::size_t) throw(std::bad_alloc); |
| /// void operator delete(void *) throw(); |
| /// void operator delete[](void *) throw(); |
| /// // C++11: |
| /// void* operator new(std::size_t); |
| /// void* operator new[](std::size_t); |
| /// void operator delete(void *) noexcept; |
| /// void operator delete[](void *) noexcept; |
| /// // C++1y: |
| /// void* operator new(std::size_t); |
| /// void* operator new[](std::size_t); |
| /// void operator delete(void *) noexcept; |
| /// void operator delete[](void *) noexcept; |
| /// void operator delete(void *, std::size_t) noexcept; |
| /// void operator delete[](void *, std::size_t) noexcept; |
| /// @endcode |
| /// Note that the placement and nothrow forms of new are *not* implicitly |
| /// declared. Their use requires including \<new\>. |
| void Sema::DeclareGlobalNewDelete() { |
| if (GlobalNewDeleteDeclared) |
| return; |
| |
| // The implicitly declared new and delete operators |
| // are not supported in OpenCL. |
| if (getLangOpts().OpenCLCPlusPlus) |
| return; |
| |
| // C++ [basic.std.dynamic]p2: |
| // [...] The following allocation and deallocation functions (18.4) are |
| // implicitly declared in global scope in each translation unit of a |
| // program |
| // |
| // C++03: |
| // void* operator new(std::size_t) throw(std::bad_alloc); |
| // void* operator new[](std::size_t) throw(std::bad_alloc); |
| // void operator delete(void*) throw(); |
| // void operator delete[](void*) throw(); |
| // C++11: |
| // void* operator new(std::size_t); |
| // void* operator new[](std::size_t); |
| // void operator delete(void*) noexcept; |
| // void operator delete[](void*) noexcept; |
| // C++1y: |
| // void* operator new(std::size_t); |
| // void* operator new[](std::size_t); |
| // void operator delete(void*) noexcept; |
| // void operator delete[](void*) noexcept; |
| // void operator delete(void*, std::size_t) noexcept; |
| // void operator delete[](void*, std::size_t) noexcept; |
| // |
| // These implicit declarations introduce only the function names operator |
| // new, operator new[], operator delete, operator delete[]. |
| // |
| // Here, we need to refer to std::bad_alloc, so we will implicitly declare |
| // "std" or "bad_alloc" as necessary to form the exception specification. |
| // However, we do not make these implicit declarations visible to name |
| // lookup. |
| if (!StdBadAlloc && !getLangOpts().CPlusPlus11) { |
| // The "std::bad_alloc" class has not yet been declared, so build it |
| // implicitly. |
| StdBadAlloc = CXXRecordDecl::Create(Context, TTK_Class, |
| getOrCreateStdNamespace(), |
| SourceLocation(), SourceLocation(), |
| &PP.getIdentifierTable().get("bad_alloc"), |
| nullptr); |
| getStdBadAlloc()->setImplicit(true); |
| } |
| if (!StdAlignValT && getLangOpts().AlignedAllocation) { |
| // The "std::align_val_t" enum class has not yet been declared, so build it |
| // implicitly. |
| auto *AlignValT = EnumDecl::Create( |
| Context, getOrCreateStdNamespace(), SourceLocation(), SourceLocation(), |
| &PP.getIdentifierTable().get("align_val_t"), nullptr, true, true, true); |
| AlignValT->setIntegerType(Context.getSizeType()); |
| AlignValT->setPromotionType(Context.getSizeType()); |
| AlignValT->setImplicit(true); |
| StdAlignValT = AlignValT; |
| } |
| |
| GlobalNewDeleteDeclared = true; |
| |
| QualType VoidPtr = Context.getPointerType(Context.VoidTy); |
| QualType SizeT = Context.getSizeType(); |
| |
| auto DeclareGlobalAllocationFunctions = [&](OverloadedOperatorKind Kind, |
| QualType Return, QualType Param) { |
| llvm::SmallVector<QualType, 3> Params; |
| Params.push_back(Param); |
| |
| // Create up to four variants of the function (sized/aligned). |
| bool HasSizedVariant = getLangOpts().SizedDeallocation && |
| (Kind == OO_Delete || Kind == OO_Array_Delete); |
| bool HasAlignedVariant = getLangOpts().AlignedAllocation; |
| |
| int NumSizeVariants = (HasSizedVariant ? 2 : 1); |
| int NumAlignVariants = (HasAlignedVariant ? 2 : 1); |
| for (int Sized = 0; Sized < NumSizeVariants; ++Sized) { |
| if (Sized) |
| Params.push_back(SizeT); |
| |
| for (int Aligned = 0; Aligned < NumAlignVariants; ++Aligned) { |
| if (Aligned) |
| |