diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 0803e65df2e2..c7f47c5c021e 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -778,24 +778,46 @@ the configuration (without a prefix: ``Auto``). class foo {}; - * ``bool AfterControlStatement`` Wrap control statements (``if``/``for``/``while``/``switch``/..). + * ``BraceWrappingAfterControlStatementStyle AfterControlStatement`` + Wrap control statements (``if``/``for``/``while``/``switch``/..). - .. code-block:: c++ + Possible values: - true: - if (foo()) - { - } else - {} - for (int i = 0; i < 10; ++i) - {} + * ``BWACS_Never`` (in configuration: ``Never``) + Never wrap braces after a control statement. - false: - if (foo()) { - } else { - } - for (int i = 0; i < 10; ++i) { - } + .. code-block:: c++ + + if (foo()) { + } else { + } + for (int i = 0; i < 10; ++i) { + } + + * ``BWACS_MultiLine`` (in configuration: ``MultiLine``) + Only wrap braces after a multi-line control statement. + + .. code-block:: c++ + + if (foo && bar && + baz) + { + quux(); + } + while (foo || bar) { + } + + * ``BWACS_Always`` (in configuration: ``Always``) + Always wrap braces after a control statement. + + .. code-block:: c++ + + if (foo()) + { + } else + {} + for (int i = 0; i < 10; ++i) + {} * ``bool AfterEnum`` Wrap enum definitions. diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 37f489c7708a..f14d3abf71e5 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_AST_CHARUNITS_H #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MathExtras.h" @@ -177,6 +178,10 @@ namespace clang { /// getQuantity - Get the raw integer representation of this quantity. QuantityType getQuantity() const { return Quantity; } + /// getAsAlign - Returns Quantity as a valid llvm::Align, + /// Beware llvm::Align assumes power of two 8-bit bytes. + llvm::Align getAsAlign() const { return llvm::Align(Quantity); } + /// alignTo - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h index d3942ee0a485..b718323b669d 100644 --- a/include/clang/AST/ExternalASTMerger.h +++ b/include/clang/AST/ExternalASTMerger.h @@ -23,7 +23,7 @@ namespace clang { /// ExternalASTSource implementation that merges information from several /// ASTContexts. /// -/// ExtermalASTMerger maintains a vector of ASTImporters that it uses to import +/// ExternalASTMerger maintains a vector of ASTImporters that it uses to import /// (potentially incomplete) Decls and DeclContexts from the source ASTContexts /// in response to ExternalASTSource API calls. /// @@ -37,7 +37,7 @@ namespace clang { /// lookup. In this case, Origins contains an entry overriding lookup and /// specifying the correct pair of DeclContext/ASTContext. /// -/// - The DeclContext of origin was determined by another ExterenalASTMerger. +/// - The DeclContext of origin was determined by another ExternalASTMerger. /// (This is possible when the source ASTContext for one of the Importers has /// its own ExternalASTMerger). The origin must be properly forwarded in this /// case. @@ -94,7 +94,7 @@ class ExternalASTMerger : public ExternalASTSource { }; private: - /// The target for this ExtenralASTMerger. + /// The target for this ExternalASTMerger. ImporterTarget Target; /// ExternalASTMerger has multiple ASTImporters that import into the same /// TU. This is the shared state for all ASTImporters of this @@ -158,7 +158,7 @@ class ExternalASTMerger : public ExternalASTSource { /// OriginContext. bool HasImporterForOrigin(ASTContext &OriginContext); - /// Returns a reference to the ASTRImporter from Importers whose origin + /// Returns a reference to the ASTImporter from Importers whose origin /// is OriginContext. This allows manual import of ASTs while preserving the /// OriginMap correctly. ASTImporter &ImporterForOrigin(ASTContext &OriginContext); diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 14834a1f5414..283d0f32007a 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -3290,12 +3290,19 @@ def OMPDeclareVariant : InheritableAttr { let Documentation = [OMPDeclareVariantDocs]; let Args = [ ExprArgument<"VariantFuncRef">, + ExprArgument<"Score">, EnumArgument<"CtxSelectorSet", "CtxSelectorSetType", [ "", "implementation" ], [ "CtxSetUnknown", "CtxSetImplementation" ]>, + EnumArgument<"CtxScore", "ScoreType", + [ "", "score" + ], + [ + "ScoreUnknown", "ScoreSpecified" + ]>, EnumArgument<"CtxSelector", "CtxSelectorType", [ "", "vendor" ], @@ -3305,6 +3312,13 @@ def OMPDeclareVariant : InheritableAttr { StringArgument<"ImplVendor", 1> ]; let AdditionalMembers = [{ + void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const { + if (const Expr *E = getScore()) { + OS << "score("; + E->printPretty(OS, nullptr, Policy); + OS << "):"; + } + } void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) const { assert(getCtxSelectorSet() != CtxSetUnknown && @@ -3322,6 +3336,7 @@ def OMPDeclareVariant : InheritableAttr { switch (getCtxSelector()) { case CtxVendor: OS << "vendor("; + printScore(OS, Policy); OS << getImplVendor(); OS << ")"; break; diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index f4eeebd73ab6..63207a0e2254 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -38,8 +38,8 @@ def note_constexpr_pure_virtual_call : Note< "pure virtual function %q0 called">; def note_constexpr_polymorphic_unknown_dynamic_type : Note< "%select{|||||virtual function called on|dynamic_cast applied to|" - "typeid applied to|destruction of}0 object '%1' whose dynamic type " - "is not constant">; + "typeid applied to|construction of|destruction of}0 object '%1' " + "whose dynamic type is not constant">; def note_constexpr_dynamic_cast_to_reference_failed : Note< "reference dynamic_cast failed: %select{" "static type %1 of operand is a non-public base class of dynamic type %2|" @@ -121,11 +121,12 @@ def note_constexpr_this : Note< "evaluation of a call to a 'constexpr' member function">; def note_constexpr_lifetime_ended : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " - "%select{temporary|variable}1 whose lifetime has ended">; + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 %select{temporary|variable}1 whose " + "%plural{8:storage duration|:lifetime}0 has ended">; def note_constexpr_access_uninit : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to||destruction of}0 " "%select{object outside its lifetime|uninitialized object}1 " "is not allowed in a constant expression">; def note_constexpr_use_uninit_reference : Note< @@ -136,18 +137,19 @@ def note_constexpr_modify_const_type : Note< "in a constant expression">; def note_constexpr_access_volatile_type : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "||}0 " + "|||}0 " "volatile-qualified type %1 is not allowed in a constant expression">; def note_constexpr_access_volatile_obj : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "||}0 " + "|||}0 " "volatile %select{temporary|object %2|member %2}1 is not allowed in " "a constant expression">; def note_constexpr_volatile_here : Note< "volatile %select{temporary created|object declared|member declared}0 here">; def note_constexpr_access_mutable : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "mutable member %1 is not allowed in a constant expression">; def note_constexpr_ltor_non_const_int : Note< "read of non-const variable %0 is not allowed in a constant expression">; @@ -157,35 +159,42 @@ def note_constexpr_ltor_incomplete_type : Note< "read of incomplete type %0 is not allowed in a constant expression">; def note_constexpr_access_null : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "dereferenced null pointer is not allowed in a constant expression">; def note_constexpr_access_past_end : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "dereferenced one-past-the-end pointer is not allowed " "in a constant expression">; def note_constexpr_access_unsized_array : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "element of array without known bound " "is not allowed in a constant expression">; def note_constexpr_access_inactive_union_member : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|" + "construction of subobject of|destruction of}0 " "member %1 of union with %select{active member %3|no active member}2 " "is not allowed in a constant expression">; def note_constexpr_access_static_temporary : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 temporary " + "member call on|dynamic_cast of|typeid applied to|reconstruction of|" + "destruction of}0 temporary " "is not allowed in a constant expression outside the expression that " "created the temporary">; def note_constexpr_access_unreadable_object : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "object '%1' whose value is not known">; def note_constexpr_access_deleted_object : Note< "%select{read of|read of|assignment to|increment of|decrement of|" - "member call on|dynamic_cast of|typeid applied to|destruction of}0 " + "member call on|dynamic_cast of|typeid applied to|construction of|" + "destruction of}0 " "heap allocated object that has been deleted">; def note_constexpr_modify_global : Note< "a constant expression cannot modify an object that is visible outside " @@ -255,6 +264,9 @@ def note_constexpr_bit_cast_indet_dest : Note< def note_constexpr_pseudo_destructor : Note< "pseudo-destructor call is not permitted in constant expressions " "until C++20">; +def note_constexpr_construct_complex_elem : Note< + "construction of individual component of complex number is not yet supported " + "in constant expressions">; def note_constexpr_destroy_complex_elem : Note< "destruction of individual component of complex number is not yet supported " "in constant expressions">; @@ -265,6 +277,8 @@ def note_constexpr_new_non_replaceable : Note< "call to %select{placement|class-specific}0 %1">; def note_constexpr_new_placement : Note< "this placement new expression is not yet supported in constant expressions">; +def note_constexpr_placement_new_wrong_type : Note< + "placement new would change type of storage from %0 to %1">; def note_constexpr_new_negative : Note< "cannot allocate array; evaluated array bound %0 is negative">; def note_constexpr_new_too_large : Note< @@ -272,6 +286,13 @@ def note_constexpr_new_too_large : Note< def note_constexpr_new_too_small : Note< "cannot allocate array; evaluated array bound %0 is too small to hold " "%1 explicitly initialized elements">; +def note_constexpr_new_untyped : Note< + "cannot allocate untyped memory in a constant expression; " + "use 'std::allocator::allocate' to allocate memory of type 'T'">; +def note_constexpr_new_not_complete_object_type : Note< + "cannot allocate memory of %select{incomplete|function}0 type %1">; +def note_constexpr_operator_new_bad_size : Note< + "allocated size %0 is not a multiple of size %1 of element type %2">; def note_constexpr_delete_not_heap_alloc : Note< "delete of pointer '%0' that does not point to a heap-allocated object">; def note_constexpr_double_delete : Note< @@ -279,8 +300,12 @@ def note_constexpr_double_delete : Note< def note_constexpr_double_destroy : Note< "destruction of object that is already being destroyed">; def note_constexpr_new_delete_mismatch : Note< - "%select{non-|}0array delete used to delete pointer to " - "%select{|non-}0array object of type %1">; + "%plural{2:'delete' used to delete pointer to object " + "allocated with 'std::allocator<...>::allocate'|" + ":%select{non-array delete|array delete|'std::allocator<...>::deallocate'}0 " + "used to delete pointer to " + "%select{array object of type %2|non-array object of type %2|" + "object allocated with 'new'}0}1">; def note_constexpr_delete_subobject : Note< "delete of pointer%select{ to subobject|}1 '%0' " "%select{|that does not point to complete object}1">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d3f27a2abdad..97993feff345 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -6211,6 +6211,8 @@ def err_invalid_qualified_function_type : Error< def err_compound_qualified_function_type : Error< "%select{block pointer|pointer|reference}0 to function type %select{%2 |}1" "cannot have '%3' qualifier">; +def err_qualified_function_typeid : Error< + "type operand %0 of 'typeid' cannot have '%1' qualifier">; def err_ref_qualifier_overload : Error< "cannot overload a member function %select{without a ref-qualifier|with " @@ -6635,6 +6637,9 @@ def note_member_declared_here : Note< "member %0 declared here">; def note_member_first_declared_here : Note< "member %0 first declared here">; +def warn_bitwise_negation_bool : Warning< + "bitwise negation of a boolean expression always evaluates to 'true'">, + InGroup>; def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< "incrementing expression of type bool is deprecated and " diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 6389e498e483..d774c04b6de5 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -782,6 +782,40 @@ struct FormatStyle { /// The brace breaking style to use. BraceBreakingStyle BreakBeforeBraces; + // Different ways to wrap braces after control statements. + enum BraceWrappingAfterControlStatementStyle { + /// Never wrap braces after a control statement. + /// \code + /// if (foo()) { + /// } else { + /// } + /// for (int i = 0; i < 10; ++i) { + /// } + /// \endcode + BWACS_Never, + /// Only wrap braces after a multi-line control statement. + /// \code + /// if (foo && bar && + /// baz) + /// { + /// quux(); + /// } + /// while (foo || bar) { + /// } + /// \endcode + BWACS_MultiLine, + /// Always wrap braces after a control statement. + /// \code + /// if (foo()) + /// { + /// } else + /// {} + /// for (int i = 0; i < 10; ++i) + /// {} + /// \endcode + BWACS_Always + }; + /// Precise control over the wrapping of braces. /// \code /// # Should be declared this way: @@ -817,23 +851,7 @@ struct FormatStyle { /// \endcode bool AfterClass; /// Wrap control statements (``if``/``for``/``while``/``switch``/..). - /// \code - /// true: - /// if (foo()) - /// { - /// } else - /// {} - /// for (int i = 0; i < 10; ++i) - /// {} - /// - /// false: - /// if (foo()) { - /// } else { - /// } - /// for (int i = 0; i < 10; ++i) { - /// } - /// \endcode - bool AfterControlStatement; + BraceWrappingAfterControlStatementStyle AfterControlStatement; /// Wrap enum definitions. /// \code /// true: diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index bc69dc267c2d..cb8631691e5b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1523,6 +1523,8 @@ class Sema { QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, SourceLocation AttrLoc); + bool CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc); + bool CheckFunctionReturnType(QualType T, SourceLocation Loc); /// Build a function type. @@ -9110,11 +9112,14 @@ class Sema { OMPDeclareVariantAttr::CtxSelectorType Ctx = OMPDeclareVariantAttr::CtxUnknown; StringRef ImplVendor; + ExprResult CtxScore; explicit OpenMPDeclareVariantCtsSelectorData() = default; explicit OpenMPDeclareVariantCtsSelectorData( OMPDeclareVariantAttr::CtxSelectorSetType CtxSet, - OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor) - : CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor) {} + OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor, + ExprResult CtxScore) + : CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor), CtxScore(CtxScore) { + } }; /// Checks if the variant/multiversion functions are compatible. diff --git a/include/clang/Tooling/Refactoring/Stencil.h b/include/clang/Tooling/Refactoring/Stencil.h index 3bd66e578b85..96fd978e945a 100644 --- a/include/clang/Tooling/Refactoring/Stencil.h +++ b/include/clang/Tooling/Refactoring/Stencil.h @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// /// -/// /file +/// \file /// This file defines the *Stencil* abstraction: a code-generating object, /// parameterized by named references to (bound) AST nodes. Given a match /// result, a stencil can be evaluated to a string of source code. @@ -154,6 +154,21 @@ inline StencilPart node(llvm::StringRef Id) { return selection(tooling::node(Id)); } +/// Generates the source of the expression bound to \p Id, wrapping it in +/// parentheses if it may parse differently depending on context. For example, a +/// binary operation is always wrapped, while a variable reference is never +/// wrapped. +StencilPart expression(llvm::StringRef Id); + +/// Constructs an idiomatic dereferencing of the expression bound to \p ExprId. +/// \p ExprId is wrapped in parentheses, if needed. +StencilPart deref(llvm::StringRef ExprId); + +/// Constructs an expression that idiomatically takes the address of the +/// expression bound to \p ExprId. \p ExprId is wrapped in parentheses, if +/// needed. +StencilPart addressOf(llvm::StringRef ExprId); + /// Constructs a `MemberExpr` that accesses the named member (\p Member) of the /// object bound to \p BaseId. The access is constructed idiomatically: if \p /// BaseId is bound to `e` and \p Member identifies member `m`, then returns diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index f29d6f5554c5..50f8d05dacb4 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -652,7 +652,7 @@ void APValue::printPretty(raw_ostream &Out, const ASTContext &Ctx, } case APValue::Struct: { Out << '{'; - const RecordDecl *RD = Ty->getAs()->getDecl(); + const RecordDecl *RD = Ty->castAs()->getDecl(); bool First = true; if (unsigned N = getStructNumBases()) { const CXXRecordDecl *CD = cast(RD); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a8809686623b..1e104f6a6dc3 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -6852,8 +6852,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S, } } else if (Options.IsOutermostType()) { QualType P = PointeeTy; - while (P->getAs()) - P = P->getAs()->getPointeeType(); + while (auto PT = P->getAs()) + P = PT->getPointeeType(); if (P.isConstQualified()) { isReadOnly = true; S += 'r'; diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 10537efebfc7..77a3a4c679a1 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -959,11 +959,11 @@ const FunctionType *Decl::getFunctionType(bool BlocksToo) const { return nullptr; if (Ty->isFunctionPointerType()) - Ty = Ty->getAs()->getPointeeType(); + Ty = Ty->castAs()->getPointeeType(); else if (Ty->isFunctionReferenceType()) - Ty = Ty->getAs()->getPointeeType(); + Ty = Ty->castAs()->getPointeeType(); else if (BlocksToo && Ty->isBlockPointerType()) - Ty = Ty->getAs()->getPointeeType(); + Ty = Ty->castAs()->getPointeeType(); return Ty->getAs(); } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 95b14e494a3b..a085941e68c5 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -218,7 +218,7 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, if (BaseType->isDependentType()) continue; auto *BaseClassDecl = - cast(BaseType->getAs()->getDecl()); + cast(BaseType->castAs()->getDecl()); // C++2a [class]p7: // A standard-layout class is a class that: @@ -1909,7 +1909,7 @@ bool CXXRecordDecl::mayBeAbstract() const { for (const auto &B : bases()) { const auto *BaseDecl = - cast(B.getType()->getAs()->getDecl()); + cast(B.getType()->castAs()->getDecl()); if (BaseDecl->isAbstract()) return true; } @@ -2566,7 +2566,7 @@ bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const { return false; return (getNumParams() == 0 && - getType()->getAs()->isVariadic()) || + getType()->castAs()->isVariadic()) || (getNumParams() == 1) || (getNumParams() > 1 && (getParamDecl(1)->hasDefaultArg() || diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index c03ae22fb5d8..ccfc292e4c6c 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -519,15 +519,15 @@ SourceRange TemplateTypeParmDecl::getSourceRange() const { } unsigned TemplateTypeParmDecl::getDepth() const { - return getTypeForDecl()->getAs()->getDepth(); + return getTypeForDecl()->castAs()->getDepth(); } unsigned TemplateTypeParmDecl::getIndex() const { - return getTypeForDecl()->getAs()->getIndex(); + return getTypeForDecl()->castAs()->getIndex(); } bool TemplateTypeParmDecl::isParameterPack() const { - return getTypeForDecl()->getAs()->isParameterPack(); + return getTypeForDecl()->castAs()->isParameterPack(); } //===----------------------------------------------------------------------===// diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c9394bba2dd5..339f471a2c01 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -85,8 +85,8 @@ const Expr *Expr::skipRValueSubobjectAdjustments( CE->getCastKind() == CK_UncheckedDerivedToBase) && E->getType()->isRecordType()) { E = CE->getSubExpr(); - CXXRecordDecl *Derived - = cast(E->getType()->getAs()->getDecl()); + auto *Derived = + cast(E->getType()->castAs()->getDecl()); Adjustments.push_back(SubobjectAdjustment(CE, Derived)); continue; } @@ -3205,7 +3205,7 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, if (ILE->getType()->isRecordType()) { unsigned ElementNo = 0; - RecordDecl *RD = ILE->getType()->getAs()->getDecl(); + RecordDecl *RD = ILE->getType()->castAs()->getDecl(); for (const auto *Field : RD->fields()) { // If this is a union, skip all the fields that aren't being initialized. if (RD->isUnion() && ILE->getInitializedFieldInUnion() != Field) diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 55776d03f0ca..169e7ae1e17b 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -594,6 +594,13 @@ namespace { Frame *getCaller() const override { return Caller; } SourceLocation getCallLocation() const override { return CallLoc; } const FunctionDecl *getCallee() const override { return Callee; } + + bool isStdFunction() const { + for (const DeclContext *DC = Callee; DC; DC = DC->getParent()) + if (DC->isStdNamespace()) + return true; + return false; + } }; /// Temporarily override 'this'. @@ -690,6 +697,37 @@ template<> struct DenseMapInfo { } namespace { + /// A dynamically-allocated heap object. + struct DynAlloc { + /// The value of this heap-allocated object. + APValue Value; + /// The allocating expression; used for diagnostics. Either a CXXNewExpr + /// or a CallExpr (the latter is for direct calls to operator new inside + /// std::allocator::allocate). + const Expr *AllocExpr = nullptr; + + enum Kind { + New, + ArrayNew, + StdAllocator + }; + + /// Get the kind of the allocation. This must match between allocation + /// and deallocation. + Kind getKind() const { + if (auto *NE = dyn_cast(AllocExpr)) + return NE->isArray() ? ArrayNew : New; + assert(isa(AllocExpr)); + return StdAllocator; + } + }; + + struct DynAllocOrder { + bool operator()(DynamicAllocLValue L, DynamicAllocLValue R) const { + return L.getIndex() < R.getIndex(); + } + }; + /// EvalInfo - This is a private struct used by the evaluator to capture /// information about a subexpression as it is folded. It retains information /// about the AST context, but also maintains information about the folded @@ -761,20 +799,6 @@ namespace { llvm::DenseMap ObjectsUnderConstruction; - /// A dynamically-allocated heap object. - struct DynAlloc { - /// The value of this heap-allocated object. - APValue Value; - /// The allocating expression; used for diagnostics. - const Expr *AllocExpr = nullptr; - }; - - struct DynAllocOrder { - bool operator()(DynamicAllocLValue L, DynamicAllocLValue R) const { - return L.getIndex() < R.getIndex(); - } - }; - /// Current heap allocations, along with the location where each was /// allocated. We use std::map here because we need stable addresses /// for the stored APValues. @@ -970,6 +994,39 @@ namespace { return Result; } + /// Information about a stack frame for std::allocator::[de]allocate. + struct StdAllocatorCaller { + unsigned FrameIndex; + QualType ElemType; + explicit operator bool() const { return FrameIndex != 0; }; + }; + + StdAllocatorCaller getStdAllocatorCaller(StringRef FnName) const { + for (const CallStackFrame *Call = CurrentCall; Call != &BottomFrame; + Call = Call->Caller) { + const auto *MD = dyn_cast_or_null(Call->Callee); + if (!MD) + continue; + const IdentifierInfo *FnII = MD->getIdentifier(); + if (!FnII || !FnII->isStr(FnName)) + continue; + + const auto *CTSD = + dyn_cast(MD->getParent()); + if (!CTSD) + continue; + + const IdentifierInfo *ClassII = CTSD->getIdentifier(); + const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); + if (CTSD->isInStdNamespace() && ClassII && + ClassII->isStr("allocator") && TAL.size() >= 1 && + TAL[0].getKind() == TemplateArgument::Type) + return {Call->Index, TAL[0].getAsType()}; + } + + return {}; + } + void performLifetimeExtension() { // Disable the cleanups for lifetime-extended temporaries. CleanupStack.erase( @@ -1345,6 +1402,7 @@ static bool isModification(AccessKinds AK) { case AK_Assign: case AK_Increment: case AK_Decrement: + case AK_Construct: case AK_Destroy: return true; } @@ -1357,7 +1415,7 @@ static bool isAnyAccess(AccessKinds AK) { /// Is this an access per the C++ definition? static bool isFormalAccess(AccessKinds AK) { - return isAnyAccess(AK) && AK != AK_Destroy; + return isAnyAccess(AK) && AK != AK_Construct && AK != AK_Destroy; } namespace { @@ -1453,9 +1511,10 @@ namespace { IsNullPtr = false; } - void setNull(QualType PointerTy, uint64_t TargetVal) { + void setNull(ASTContext &Ctx, QualType PointerTy) { Base = (Expr *)nullptr; - Offset = CharUnits::fromQuantity(TargetVal); + Offset = + CharUnits::fromQuantity(Ctx.getTargetNullPointerValue(PointerTy)); InvalidBase = false; Designator = SubobjectDesignator(PointerTy->getPointeeType()); IsNullPtr = true; @@ -1465,6 +1524,12 @@ namespace { set(B, true); } + std::string toString(ASTContext &Ctx, QualType T) const { + APValue Printable; + moveInto(Printable); + return Printable.getAsString(Ctx, T); + } + private: // Check that this LValue is not based on a null pointer. If it is, produce // a diagnostic and mark the designator as invalid. @@ -1905,7 +1970,7 @@ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { Info.Note(E->getExprLoc(), diag::note_constexpr_temporary_here); else if (DynamicAllocLValue DA = Base.dyn_cast()) { // FIXME: Produce a note for dangling pointers too. - if (Optional Alloc = Info.lookupDynamicAlloc(DA)) + if (Optional Alloc = Info.lookupDynamicAlloc(DA)) Info.Note((*Alloc)->AllocExpr->getExprLoc(), diag::note_constexpr_dynamic_alloc_here); } @@ -3113,8 +3178,9 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, // Walk the designator's path to find the subobject. for (unsigned I = 0, N = Sub.Entries.size(); /**/; ++I) { // Reading an indeterminate value is undefined, but assigning over one is OK. - if (O->isAbsent() || - (O->isIndeterminate() && handler.AccessKind != AK_Assign && + if ((O->isAbsent() && handler.AccessKind != AK_Construct) || + (O->isIndeterminate() && handler.AccessKind != AK_Construct && + handler.AccessKind != AK_Assign && handler.AccessKind != AK_ReadObjectRepresentation)) { if (!Info.checkingPotentialConstantExpression()) Info.FFDiag(E, diag::note_constexpr_access_uninit) @@ -3254,13 +3320,18 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, const FieldDecl *UnionField = O->getUnionField(); if (!UnionField || UnionField->getCanonicalDecl() != Field->getCanonicalDecl()) { - // FIXME: If O->getUnionValue() is absent, report that there's no - // active union member rather than reporting the prior active union - // member. We'll need to fix nullptr_t to not use APValue() as its - // representation first. - Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) - << handler.AccessKind << Field << !UnionField << UnionField; - return handler.failed(); + if (I == N - 1 && handler.AccessKind == AK_Construct) { + // Placement new onto an inactive union member makes it active. + O->setUnion(Field, APValue()); + } else { + // FIXME: If O->getUnionValue() is absent, report that there's no + // active union member rather than reporting the prior active union + // member. We'll need to fix nullptr_t to not use APValue() as its + // representation first. + Info.FFDiag(E, diag::note_constexpr_access_inactive_union_member) + << handler.AccessKind << Field << !UnionField << UnionField; + return handler.failed(); + } } O = &O->getUnionValue(); } else @@ -3560,7 +3631,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, if (!evaluateVarDeclInit(Info, E, VD, Frame, BaseVal, &LVal)) return CompleteObject(); } else if (DynamicAllocLValue DA = LVal.Base.dyn_cast()) { - Optional Alloc = Info.lookupDynamicAlloc(DA); + Optional Alloc = Info.lookupDynamicAlloc(DA); if (!Alloc) { Info.FFDiag(E, diag::note_constexpr_access_deleted_object) << AK; return CompleteObject(); @@ -5147,8 +5218,7 @@ static bool HandleDynamicCast(EvalInfo &Info, const ExplicitCastExpr *E, if (!E->isGLValue()) { // The value of a failed cast to pointer type is the null pointer value // of the required result type. - auto TargetVal = Info.Ctx.getTargetNullPointerValue(E->getType()); - Ptr.setNull(E->getType(), TargetVal); + Ptr.setNull(Info.Ctx, E->getType()); return true; } @@ -5878,6 +5948,161 @@ static bool HandleDestruction(EvalInfo &Info, SourceLocation Loc, return HandleDestructionImpl(Info, Loc, LV, Value, T); } +/// Perform a call to 'perator new' or to `__builtin_operator_new'. +static bool HandleOperatorNewCall(EvalInfo &Info, const CallExpr *E, + LValue &Result) { + if (Info.checkingPotentialConstantExpression() || + Info.SpeculativeEvaluationDepth) + return false; + + // This is permitted only within a call to std::allocator::allocate. + auto Caller = Info.getStdAllocatorCaller("allocate"); + if (!Caller) { + Info.FFDiag(E->getExprLoc(), Info.getLangOpts().CPlusPlus2a + ? diag::note_constexpr_new_untyped + : diag::note_constexpr_new); + return false; + } + + QualType ElemType = Caller.ElemType; + if (ElemType->isIncompleteType() || ElemType->isFunctionType()) { + Info.FFDiag(E->getExprLoc(), + diag::note_constexpr_new_not_complete_object_type) + << (ElemType->isIncompleteType() ? 0 : 1) << ElemType; + return false; + } + + APSInt ByteSize; + if (!EvaluateInteger(E->getArg(0), ByteSize, Info)) + return false; + bool IsNothrow = false; + for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) { + EvaluateIgnoredValue(Info, E->getArg(I)); + IsNothrow |= E->getType()->isNothrowT(); + } + + CharUnits ElemSize; + if (!HandleSizeof(Info, E->getExprLoc(), ElemType, ElemSize)) + return false; + APInt Size, Remainder; + APInt ElemSizeAP(ByteSize.getBitWidth(), ElemSize.getQuantity()); + APInt::udivrem(ByteSize, ElemSizeAP, Size, Remainder); + if (Remainder != 0) { + // This likely indicates a bug in the implementation of 'std::allocator'. + Info.FFDiag(E->getExprLoc(), diag::note_constexpr_operator_new_bad_size) + << ByteSize << APSInt(ElemSizeAP, true) << ElemType; + return false; + } + + if (ByteSize.getActiveBits() > ConstantArrayType::getMaxSizeBits(Info.Ctx)) { + if (IsNothrow) { + Result.setNull(Info.Ctx, E->getType()); + return true; + } + + Info.FFDiag(E, diag::note_constexpr_new_too_large) << APSInt(Size, true); + return false; + } + + QualType AllocType = + Info.Ctx.getConstantArrayType(ElemType, Size, ArrayType::Normal, 0); + APValue *Val = Info.createHeapAlloc(E, AllocType, Result); + *Val = APValue(APValue::UninitArray(), 0, Size.getZExtValue()); + Result.addArray(Info, E, cast(AllocType)); + return true; +} + +static bool hasVirtualDestructor(QualType T) { + if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) + if (CXXDestructorDecl *DD = RD->getDestructor()) + return DD->isVirtual(); + return false; +} + +/// Check that the given object is a suitable pointer to a heap allocation that +/// still exists and is of the right kind for the purpose of a deletion. +/// +/// On success, returns the heap allocation to deallocate. On failure, produces +/// a diagnostic and returns None. +static Optional CheckDeleteKind(EvalInfo &Info, const Expr *E, + const LValue &Pointer, + DynAlloc::Kind DeallocKind) { + auto PointerAsString = [&] { + return Pointer.toString(Info.Ctx, Info.Ctx.VoidPtrTy); + }; + + DynamicAllocLValue DA = Pointer.Base.dyn_cast(); + if (!DA) { + Info.FFDiag(E, diag::note_constexpr_delete_not_heap_alloc) + << PointerAsString(); + if (Pointer.Base) + NoteLValueLocation(Info, Pointer.Base); + return None; + } + + Optional Alloc = Info.lookupDynamicAlloc(DA); + if (!Alloc) { + Info.FFDiag(E, diag::note_constexpr_double_delete); + return None; + } + + QualType AllocType = Pointer.Base.getDynamicAllocType(); + if (DeallocKind != (*Alloc)->getKind()) { + Info.FFDiag(E, diag::note_constexpr_new_delete_mismatch) + << DeallocKind << (*Alloc)->getKind() << AllocType; + NoteLValueLocation(Info, Pointer.Base); + return None; + } + + bool Subobject = false; + if (DeallocKind == DynAlloc::New) { + Subobject = Pointer.Designator.MostDerivedPathLength != 0 || + Pointer.Designator.isOnePastTheEnd(); + } else { + Subobject = Pointer.Designator.Entries.size() != 1 || + Pointer.Designator.Entries[0].getAsArrayIndex() != 0; + } + if (Subobject) { + Info.FFDiag(E, diag::note_constexpr_delete_subobject) + << PointerAsString() << Pointer.Designator.isOnePastTheEnd(); + return None; + } + + return Alloc; +} + +// Perform a call to 'operator delete' or '__builtin_operator_delete'. +bool HandleOperatorDeleteCall(EvalInfo &Info, const CallExpr *E) { + if (Info.checkingPotentialConstantExpression() || + Info.SpeculativeEvaluationDepth) + return false; + + // This is permitted only within a call to std::allocator::deallocate. + if (!Info.getStdAllocatorCaller("deallocate")) { + Info.FFDiag(E->getExprLoc()); + return true; + } + + LValue Pointer; + if (!EvaluatePointer(E->getArg(0), Pointer, Info)) + return false; + for (unsigned I = 1, N = E->getNumArgs(); I != N; ++I) + EvaluateIgnoredValue(Info, E->getArg(I)); + + if (Pointer.Designator.Invalid) + return false; + + // Deleting a null pointer has no effect. + if (Pointer.isNullPointer()) + return true; + + if (!CheckDeleteKind(Info, E, Pointer, DynAlloc::StdAllocator)) + return false; + + Info.HeapAllocs.erase(Pointer.Base.get()); + return true; +} + //===----------------------------------------------------------------------===// // Generic Evaluation //===----------------------------------------------------------------------===// @@ -6210,9 +6435,8 @@ class BufferToAPValueConverter { QualType RepresentationType = Ty->getDecl()->getIntegerType(); assert(!RepresentationType.isNull() && "enum forward decl should be caught by Sema"); - const BuiltinType *AsBuiltin = - RepresentationType.getCanonicalType()->getAs(); - assert(AsBuiltin && "non-integral enum underlying type?"); + const auto *AsBuiltin = + RepresentationType.getCanonicalType()->castAs(); // Recurse into the underlying type. Treat std::byte transparently as // unsigned char. return visit(AsBuiltin, Offset, /*EnumTy=*/Ty); @@ -6620,8 +6844,11 @@ class ExprEvaluatorBase HasQualifier = ME->hasQualifier(); } else if (const BinaryOperator *BE = dyn_cast(Callee)) { // Indirect bound member calls ('.*' or '->*'). - Member = dyn_cast_or_null( - HandleMemberPointerAccess(Info, BE, ThisVal, false)); + const ValueDecl *D = + HandleMemberPointerAccess(Info, BE, ThisVal, false); + if (!D) + return false; + Member = dyn_cast(D); if (!Member) return Error(Callee); This = &ThisVal; @@ -6700,6 +6927,17 @@ class ExprEvaluatorBase FD = cast(CorrespondingCallOpSpecialization); } else FD = LambdaCallOp; + } else if (FD->isReplaceableGlobalAllocationFunction()) { + if (FD->getDeclName().getCXXOverloadedOperator() == OO_New || + FD->getDeclName().getCXXOverloadedOperator() == OO_Array_New) { + LValue Ptr; + if (!HandleOperatorNewCall(Info, E, Ptr)) + return false; + Ptr.moveInto(Result); + return true; + } else { + return HandleOperatorDeleteCall(Info, E); + } } } else return Error(E); @@ -6972,7 +7210,7 @@ class LValueExprEvaluatorBase const ValueDecl *MD = E->getMemberDecl(); if (const FieldDecl *FD = dyn_cast(E->getMemberDecl())) { - assert(BaseTy->getAs()->getDecl()->getCanonicalDecl() == + assert(BaseTy->castAs()->getDecl()->getCanonicalDecl() == FD->getParent()->getCanonicalDecl() && "record / field mismatch"); (void)BaseTy; if (!HandleLValueMember(this->Info, E, Result, FD)) @@ -7565,8 +7803,7 @@ class PointerExprEvaluator return true; } bool ZeroInitialization(const Expr *E) { - auto TargetVal = Info.Ctx.getTargetNullPointerValue(E->getType()); - Result.setNull(E->getType(), TargetVal); + Result.setNull(Info.Ctx, E->getType()); return true; } @@ -7693,12 +7930,22 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { // permitted in constant expressions in C++11. Bitcasts from cv void* are // also static_casts, but we disallow them as a resolution to DR1312. if (!E->getType()->isVoidPointerType()) { - Result.Designator.setInvalid(); - if (SubExpr->getType()->isVoidPointerType()) - CCEDiag(E, diag::note_constexpr_invalid_cast) - << 3 << SubExpr->getType(); - else - CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + if (!Result.InvalidBase && !Result.Designator.Invalid && + !Result.IsNullPtr && + Info.Ctx.hasSameUnqualifiedType(Result.Designator.getType(Info.Ctx), + E->getType()->getPointeeType()) && + Info.getStdAllocatorCaller("allocate")) { + // Inside a call to std::allocator::allocate and friends, we permit + // casting from void* back to cv1 T* for a pointer that points to a + // cv2 T. + } else { + Result.Designator.setInvalid(); + if (SubExpr->getType()->isVoidPointerType()) + CCEDiag(E, diag::note_constexpr_invalid_cast) + << 3 << SubExpr->getType(); + else + CCEDiag(E, diag::note_constexpr_invalid_cast) << 2; + } } if (E->getCastKind() == CK_AddressSpaceConversion && Result.IsNullPtr) ZeroInitialization(E); @@ -7935,6 +8182,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return true; } + case Builtin::BI__builtin_operator_new: + return HandleOperatorNewCall(Info, E, Result); case Builtin::BI__builtin_launder: return evaluatePointer(E->getArg(0), Result); case Builtin::BIstrchr: @@ -8186,8 +8435,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, } default: - return visitNonBuiltinCallExpr(E); + break; } + + return visitNonBuiltinCallExpr(E); } static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, @@ -8203,14 +8454,23 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { return false; FunctionDecl *OperatorNew = E->getOperatorNew(); - if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { + + bool IsNothrow = false; + bool IsPlacement = false; + if (OperatorNew->isReservedGlobalPlacementOperator() && + Info.CurrentCall->isStdFunction() && !E->isArray()) { + // FIXME Support array placement new. + assert(E->getNumPlacementArgs() == 1); + if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) + return false; + if (Result.Designator.Invalid) + return false; + IsPlacement = true; + } else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) { Info.FFDiag(E, diag::note_constexpr_new_non_replaceable) << isa(OperatorNew) << OperatorNew; return false; - } - - bool IsNothrow = false; - if (E->getNumPlacementArgs()) { + } else if (E->getNumPlacementArgs()) { // The only new-placement list we support is of the form (std::nothrow). // // FIXME: There is no restriction on this, but it's not clear that any @@ -8308,10 +8568,56 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { "array allocation with non-array new"); } - // Perform the allocation and obtain a pointer to the resulting object. - APValue *Val = Info.createHeapAlloc(E, AllocType, Result); - if (!Val) - return false; + APValue *Val; + if (IsPlacement) { + AccessKinds AK = AK_Construct; + struct FindObjectHandler { + EvalInfo &Info; + const Expr *E; + QualType AllocType; + const AccessKinds AccessKind; + APValue *Value; + + typedef bool result_type; + bool failed() { return false; } + bool found(APValue &Subobj, QualType SubobjType) { + // FIXME: Reject the cases where [basic.life]p8 would not permit the + // old name of the object to be used to name the new object. + if (!Info.Ctx.hasSameUnqualifiedType(SubobjType, AllocType)) { + Info.FFDiag(E, diag::note_constexpr_placement_new_wrong_type) << + SubobjType << AllocType; + return false; + } + Value = &Subobj; + return true; + } + bool found(APSInt &Value, QualType SubobjType) { + Info.FFDiag(E, diag::note_constexpr_construct_complex_elem); + return false; + } + bool found(APFloat &Value, QualType SubobjType) { + Info.FFDiag(E, diag::note_constexpr_construct_complex_elem); + return false; + } + } Handler = {Info, E, AllocType, AK, nullptr}; + + CompleteObject Obj = findCompleteObject(Info, E, AK, Result, AllocType); + if (!Obj || !findSubobject(Info, E, Obj, Result.Designator, Handler)) + return false; + + Val = Handler.Value; + + // [basic.life]p1: + // The lifetime of an object o of type T ends when [...] the storage + // which the object occupies is [...] reused by an object that is not + // nested within o (6.6.2). + *Val = APValue(); + } else { + // Perform the allocation and obtain a pointer to the resulting object. + Val = Info.createHeapAlloc(E, AllocType, Result); + if (!Val) + return false; + } if (ResizedArrayILE) { if (!EvaluateArrayNewInitList(Info, Result, *Val, ResizedArrayILE, @@ -9053,7 +9359,7 @@ VectorExprEvaluator::VisitInitListExpr(const InitListExpr *E) { bool VectorExprEvaluator::ZeroInitialization(const Expr *E) { - const VectorType *VT = E->getType()->getAs(); + const auto *VT = E->getType()->castAs(); QualType EltTy = VT->getElementType(); APValue ZeroElement; if (EltTy->isIntegerType()) @@ -11529,7 +11835,7 @@ bool IntExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { Info.CCEDiag(E, diag::note_constexpr_pointer_subtraction_not_same_array); QualType Type = E->getLHS()->getType(); - QualType ElementType = Type->getAs()->getPointeeType(); + QualType ElementType = Type->castAs()->getPointeeType(); CharUnits ElementSize; if (!HandleSizeof(Info, E->getExprLoc(), ElementType, ElementSize)) @@ -12426,9 +12732,9 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!Visit(E->getSubExpr())) return false; - QualType To = E->getType()->getAs()->getElementType(); + QualType To = E->getType()->castAs()->getElementType(); QualType From - = E->getSubExpr()->getType()->getAs()->getElementType(); + = E->getSubExpr()->getType()->castAs()->getElementType(); return HandleFloatToFloatCast(Info, E, From, To, Result.FloatReal) && HandleFloatToFloatCast(Info, E, From, To, Result.FloatImag); @@ -12438,9 +12744,9 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!Visit(E->getSubExpr())) return false; - QualType To = E->getType()->getAs()->getElementType(); + QualType To = E->getType()->castAs()->getElementType(); QualType From - = E->getSubExpr()->getType()->getAs()->getElementType(); + = E->getSubExpr()->getType()->castAs()->getElementType(); Result.makeComplexInt(); return HandleFloatToIntCast(Info, E, From, Result.FloatReal, To, Result.IntReal) && @@ -12462,9 +12768,9 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { if (!Visit(E->getSubExpr())) return false; - QualType To = E->getType()->getAs()->getElementType(); + QualType To = E->getType()->castAs()->getElementType(); QualType From - = E->getSubExpr()->getType()->getAs()->getElementType(); + = E->getSubExpr()->getType()->castAs()->getElementType(); Result.IntReal = HandleIntToIntCast(Info, E, To, From, Result.IntReal); Result.IntImag = HandleIntToIntCast(Info, E, To, From, Result.IntImag); @@ -12838,26 +13144,25 @@ class VoidExprEvaluator bool VisitCallExpr(const CallExpr *E) { switch (E->getBuiltinCallee()) { - default: - return ExprEvaluatorBaseTy::VisitCallExpr(E); case Builtin::BI__assume: case Builtin::BI__builtin_assume: // The argument is not evaluated! return true; + + case Builtin::BI__builtin_operator_delete: + return HandleOperatorDeleteCall(Info, E); + + default: + break; } + + return ExprEvaluatorBaseTy::VisitCallExpr(E); } bool VisitCXXDeleteExpr(const CXXDeleteExpr *E); }; } // end anonymous namespace -static bool hasVirtualDestructor(QualType T) { - if (CXXRecordDecl *RD = T->getAsCXXRecordDecl()) - if (CXXDestructorDecl *DD = RD->getDestructor()) - return DD->isVirtual(); - return false; -} - bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { // We cannot speculatively evaluate a delete expression. if (Info.SpeculativeEvaluationDepth) @@ -12888,49 +13193,12 @@ bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { return true; } - auto PointerAsString = [&] { - APValue Printable; - Pointer.moveInto(Printable); - return Printable.getAsString(Info.Ctx, Arg->getType()); - }; - - DynamicAllocLValue DA = Pointer.Base.dyn_cast(); - if (!DA) { - Info.FFDiag(E, diag::note_constexpr_delete_not_heap_alloc) - << PointerAsString(); - if (Pointer.Base) - NoteLValueLocation(Info, Pointer.Base); + Optional Alloc = CheckDeleteKind( + Info, E, Pointer, E->isArrayForm() ? DynAlloc::ArrayNew : DynAlloc::New); + if (!Alloc) return false; - } QualType AllocType = Pointer.Base.getDynamicAllocType(); - Optional Alloc = Info.lookupDynamicAlloc(DA); - if (!Alloc) { - Info.FFDiag(E, diag::note_constexpr_double_delete); - return false; - } - - if (E->isArrayForm() != AllocType->isConstantArrayType()) { - Info.FFDiag(E, diag::note_constexpr_new_delete_mismatch) - << E->isArrayForm() << AllocType; - NoteLValueLocation(Info, Pointer.Base); - return false; - } - - bool Subobject = false; - if (E->isArrayForm()) { - Subobject = Pointer.Designator.Entries.size() != 1 || - Pointer.Designator.Entries[0].getAsArrayIndex() != 0; - } else { - Subobject = Pointer.Designator.MostDerivedPathLength != 0 || - Pointer.Designator.isOnePastTheEnd(); - } - if (Subobject) { - Info.FFDiag(E, diag::note_constexpr_delete_subobject) - << PointerAsString() << Pointer.Designator.isOnePastTheEnd(); - return false; - } - // For the non-array case, the designator must be empty if the static type // does not have a virtual destructor. if (!E->isArrayForm() && Pointer.Designator.Entries.size() != 0 && @@ -12944,7 +13212,7 @@ bool VoidExprEvaluator::VisitCXXDeleteExpr(const CXXDeleteExpr *E) { (*Alloc)->Value, AllocType)) return false; - if (!Info.HeapAllocs.erase(DA)) { + if (!Info.HeapAllocs.erase(Pointer.Base.dyn_cast())) { // The element was already erased. This means the destructor call also // deleted the object. // FIXME: This probably results in undefined behavior before we get this diff --git a/lib/AST/InheritViz.cpp b/lib/AST/InheritViz.cpp index 4b3d5bee5631..2ed0ce1c79c5 100644 --- a/lib/AST/InheritViz.cpp +++ b/lib/AST/InheritViz.cpp @@ -90,8 +90,8 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) { Out << " \"];\n"; // Display the base classes. - const CXXRecordDecl *Decl - = static_cast(Type->getAs()->getDecl()); + const auto *Decl = + static_cast(Type->castAs()->getDecl()); for (const auto &Base : Decl->bases()) { QualType CanonBaseType = Context.getCanonicalType(Base.getType()); diff --git a/lib/AST/Interp/Program.cpp b/lib/AST/Interp/Program.cpp index c8c6e3762246..d947b4746f8c 100644 --- a/lib/AST/Interp/Program.cpp +++ b/lib/AST/Interp/Program.cpp @@ -238,7 +238,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { if (Spec.isVirtual()) continue; - const RecordDecl *BD = Spec.getType()->getAs()->getDecl(); + const RecordDecl *BD = Spec.getType()->castAs()->getDecl(); Record *BR = getOrCreateRecord(BD); if (Descriptor *Desc = GetBaseDesc(BD, BR)) { Size += align(sizeof(InlineDescriptor)); @@ -250,7 +250,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) { } for (const CXXBaseSpecifier &Spec : CD->vbases()) { - const RecordDecl *BD = Spec.getType()->getAs()->getDecl(); + const RecordDecl *BD = Spec.getType()->castAs()->getDecl(); Record *BR = getOrCreateRecord(BD); if (Descriptor *Desc = GetBaseDesc(BD, BR)) { diff --git a/lib/AST/Interp/State.h b/lib/AST/Interp/State.h index d02751693f6e..d9a645a3eb3e 100644 --- a/lib/AST/Interp/State.h +++ b/lib/AST/Interp/State.h @@ -32,6 +32,7 @@ enum AccessKinds { AK_MemberCall, AK_DynamicCast, AK_TypeId, + AK_Construct, AK_Destroy, }; diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 5f366a910180..93174ea8d8ec 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1330,7 +1330,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, if (const VarDecl *VD = dyn_cast(ND)) { // We must have an anonymous union or struct declaration. - const RecordDecl *RD = VD->getType()->getAs()->getDecl(); + const RecordDecl *RD = VD->getType()->castAs()->getDecl(); // Itanium C++ ABI 5.1.2: // diff --git a/lib/AST/JSONNodeDumper.cpp b/lib/AST/JSONNodeDumper.cpp index 049ce0d6ff24..2f76a1766727 100644 --- a/lib/AST/JSONNodeDumper.cpp +++ b/lib/AST/JSONNodeDumper.cpp @@ -286,7 +286,7 @@ llvm::json::Array JSONNodeDumper::createCastPath(const CastExpr *C) { for (auto I = C->path_begin(), E = C->path_end(); I != E; ++I) { const CXXBaseSpecifier *Base = *I; const auto *RD = - cast(Base->getType()->getAs()->getDecl()); + cast(Base->getType()->castAs()->getDecl()); llvm::json::Object Val{{"name", RD->getName()}}; if (Base->isVirtual()) diff --git a/lib/AST/TextNodeDumper.cpp b/lib/AST/TextNodeDumper.cpp index a540346ad459..9b76652277c9 100644 --- a/lib/AST/TextNodeDumper.cpp +++ b/lib/AST/TextNodeDumper.cpp @@ -636,8 +636,8 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) { if (!First) OS << " -> "; - const CXXRecordDecl *RD = - cast(Base->getType()->getAs()->getDecl()); + const auto *RD = + cast(Base->getType()->castAs()->getDecl()); if (Base->isVirtual()) OS << "virtual "; diff --git a/lib/AST/VTTBuilder.cpp b/lib/AST/VTTBuilder.cpp index 53d0ef09f14c..d58e87517785 100644 --- a/lib/AST/VTTBuilder.cpp +++ b/lib/AST/VTTBuilder.cpp @@ -64,8 +64,8 @@ void VTTBuilder::LayoutSecondaryVTTs(BaseSubobject Base) { if (I.isVirtual()) continue; - const CXXRecordDecl *BaseDecl = - cast(I.getType()->getAs()->getDecl()); + const auto *BaseDecl = + cast(I.getType()->castAs()->getDecl()); const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); CharUnits BaseOffset = Base.getBaseOffset() + @@ -90,8 +90,8 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, return; for (const auto &I : RD->bases()) { - const CXXRecordDecl *BaseDecl = - cast(I.getType()->getAs()->getDecl()); + const auto *BaseDecl = + cast(I.getType()->castAs()->getDecl()); // Itanium C++ ABI 2.6.2: // Secondary virtual pointers are present for all bases with either @@ -154,8 +154,8 @@ VTTBuilder::LayoutSecondaryVirtualPointers(BaseSubobject Base, void VTTBuilder::LayoutVirtualVTTs(const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases) { for (const auto &I : RD->bases()) { - const CXXRecordDecl *BaseDecl = - cast(I.getType()->getAs()->getDecl()); + const auto *BaseDecl = + cast(I.getType()->castAs()->getDecl()); // Check if this is a virtual base. if (I.isVirtual()) { diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index f87a6d6ec4a6..527e512e6aac 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -11193,7 +11193,7 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // Unaligned nontemporal store of the scalar value. StoreInst *SI = Builder.CreateDefaultAlignedStore(Src, BC); SI->setMetadata(CGM.getModule().getMDKindID("nontemporal"), Node); - SI->setAlignment(1); + SI->setAlignment(llvm::Align::None()); return SI; } // Rotate is a special case of funnel shift - 1st 2 args are the same. diff --git a/lib/CodeGen/CGCUDANV.cpp b/lib/CodeGen/CGCUDANV.cpp index aef31179884d..ee38ced0aae3 100644 --- a/lib/CodeGen/CGCUDANV.cpp +++ b/lib/CodeGen/CGCUDANV.cpp @@ -93,7 +93,7 @@ class CGNVCUDARuntime : public CGCUDARuntime { GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); } if (Alignment) - GV->setAlignment(Alignment); + GV->setAlignment(llvm::Align(Alignment)); return llvm::ConstantExpr::getGetElementPtr(ConstStr.getElementType(), ConstStr.getPointer(), Zeros); @@ -640,7 +640,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { Linkage, /*Initializer=*/llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__hip_gpubin_handle"); - GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); + GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getAsAlign()); // Prevent the weak symbol in different shared libraries being merged. if (Linkage != llvm::GlobalValue::InternalLinkage) GpuBinaryHandle->setVisibility(llvm::GlobalValue::HiddenVisibility); @@ -681,7 +681,7 @@ llvm::Function *CGNVCUDARuntime::makeModuleCtorFunction() { GpuBinaryHandle = new llvm::GlobalVariable( TheModule, VoidPtrPtrTy, false, llvm::GlobalValue::InternalLinkage, llvm::ConstantPointerNull::get(VoidPtrPtrTy), "__cuda_gpubin_handle"); - GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getQuantity()); + GpuBinaryHandle->setAlignment(CGM.getPointerAlign().getAsAlign()); CtorBuilder.CreateAlignedStore(RegisterFatbinCall, GpuBinaryHandle, CGM.getPointerAlign()); diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 6d903a0d09e2..a39bf0f6de2f 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -80,7 +80,7 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { // Skip base classes with trivial destructors. const auto *Base = - cast(I.getType()->getAs()->getDecl()); + cast(I.getType()->castAs()->getDecl()); if (Base->hasTrivialDestructor()) continue; // If we've already found a base class with a non-trivial diff --git a/lib/CodeGen/CGCXXABI.cpp b/lib/CodeGen/CGCXXABI.cpp index 041c0f8959fd..23dae2b61d04 100644 --- a/lib/CodeGen/CGCXXABI.cpp +++ b/lib/CodeGen/CGCXXABI.cpp @@ -46,8 +46,8 @@ CGCallee CGCXXABI::EmitLoadOfMemberFunctionPointer( ThisPtrForCall = This.getPointer(); const FunctionProtoType *FPT = MPT->getPointeeType()->getAs(); - const CXXRecordDecl *RD = - cast(MPT->getClass()->getAs()->getDecl()); + const auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); llvm::Constant *FnPtr = llvm::Constant::getNullValue(FTy->getPointerTo()); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index fc514beab17d..e851d7bafd76 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -3092,7 +3092,7 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, // Deactivate the cleanup for the callee-destructed param that was pushed. if (hasAggregateEvaluationKind(type) && !CurFuncIsThunk && - type->getAs()->getDecl()->isParamDestroyedInCallee() && + type->castAs()->getDecl()->isParamDestroyedInCallee() && param->needsDestruction(getContext())) { EHScopeStack::stable_iterator cleanup = CalleeDestructedParamCleanups.lookup(cast(param)); @@ -3577,7 +3577,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, // However, we still have to push an EH-only cleanup in case we unwind before // we make it to the call. if (HasAggregateEvalKind && - type->getAs()->getDecl()->isParamDestroyedInCallee()) { + type->castAs()->getDecl()->isParamDestroyedInCallee()) { // If we're using inalloca, use the argument memory. Otherwise, use a // temporary. AggValueSlot Slot; @@ -3841,7 +3841,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, AI = CreateTempAlloca(ArgStruct, "argmem"); } auto Align = CallInfo.getArgStructAlignment(); - AI->setAlignment(llvm::MaybeAlign(Align.getQuantity())); + AI->setAlignment(Align.getAsAlign()); AI->setUsedWithInAlloca(true); assert(AI->isUsedWithInAlloca() && !AI->isStaticAlloca()); ArgMemory = Address(AI, Align); diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 76ab88523971..f228329ad9b6 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -161,8 +161,8 @@ CharUnits CodeGenModule::computeNonVirtualBaseClassOffset( // Get the layout. const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); + const auto *BaseDecl = + cast(Base->getType()->castAs()->getDecl()); // Add the offset. Offset += Layout.getBaseClassOffset(BaseDecl); @@ -279,8 +279,8 @@ Address CodeGenFunction::GetAddressOfBaseClass( // *start* with a step down to the correct virtual base subobject, // and hence will not require any further steps. if ((*Start)->isVirtual()) { - VBase = - cast((*Start)->getType()->getAs()->getDecl()); + VBase = cast( + (*Start)->getType()->castAs()->getDecl()); ++Start; } @@ -536,8 +536,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, Address ThisPtr = CGF.LoadCXXThisAddress(); const Type *BaseType = BaseInit->getBaseClass(); - CXXRecordDecl *BaseClassDecl = - cast(BaseType->getAs()->getDecl()); + const auto *BaseClassDecl = + cast(BaseType->castAs()->getDecl()); bool isBaseVirtual = BaseInit->isBaseVirtual(); @@ -1245,7 +1245,7 @@ namespace { static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) { const Type *BaseType = BaseInit->getBaseClass(); const auto *BaseClassDecl = - cast(BaseType->getAs()->getDecl()); + cast(BaseType->castAs()->getDecl()); return BaseClassDecl->isDynamicClass(); } @@ -1814,8 +1814,8 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD, // We push them in the forward order so that they'll be popped in // the reverse order. for (const auto &Base : ClassDecl->vbases()) { - CXXRecordDecl *BaseClassDecl - = cast(Base.getType()->getAs()->getDecl()); + auto *BaseClassDecl = + cast(Base.getType()->castAs()->getDecl()); // Ignore trivial destructors. if (BaseClassDecl->hasTrivialDestructor()) @@ -2530,8 +2530,8 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base, // Traverse bases. for (const auto &I : RD->bases()) { - CXXRecordDecl *BaseDecl - = cast(I.getType()->getAs()->getDecl()); + auto *BaseDecl = + cast(I.getType()->castAs()->getDecl()); // Ignore classes without a vtable. if (!BaseDecl->isDynamicClass()) diff --git a/lib/CodeGen/CGCleanup.cpp b/lib/CodeGen/CGCleanup.cpp index 1280bdb1932e..c117dd5c25c1 100644 --- a/lib/CodeGen/CGCleanup.cpp +++ b/lib/CodeGen/CGCleanup.cpp @@ -304,13 +304,13 @@ void EHScopeStack::Cleanup::anchor() {} static void createStoreInstBefore(llvm::Value *value, Address addr, llvm::Instruction *beforeInst) { auto store = new llvm::StoreInst(value, addr.getPointer(), beforeInst); - store->setAlignment(addr.getAlignment().getQuantity()); + store->setAlignment(addr.getAlignment().getAsAlign()); } static llvm::LoadInst *createLoadInstBefore(Address addr, const Twine &name, llvm::Instruction *beforeInst) { auto load = new llvm::LoadInst(addr.getPointer(), name, beforeInst); - load->setAlignment(llvm::MaybeAlign(addr.getAlignment().getQuantity())); + load->setAlignment(addr.getAlignment().getAsAlign()); return load; } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 71d99bc551c4..576d1b63310f 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1699,7 +1699,7 @@ void CGDebugInfo::CollectCXXBasesAux( const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); for (const auto &BI : Bases) { const auto *Base = - cast(BI.getType()->getAs()->getDecl()); + cast(BI.getType()->castAs()->getDecl()); if (!SeenTypes.insert(Base).second) continue; auto *BaseTy = getOrCreateType(BI.getType(), Unit); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 5c0d52a16332..46ea9c32eeed 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -250,7 +250,7 @@ llvm::Constant *CodeGenModule::getOrCreateStaticVarDecl( llvm::GlobalVariable *GV = new llvm::GlobalVariable( getModule(), LTy, Ty.isConstant(getContext()), Linkage, Init, Name, nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); - GV->setAlignment(getContext().getDeclAlign(&D).getQuantity()); + GV->setAlignment(getContext().getDeclAlign(&D).getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); @@ -408,7 +408,7 @@ void CodeGenFunction::EmitStaticVarDecl(const VarDecl &D, if (D.getInit() && !isCudaSharedVar) var = AddInitializerToStaticVarDecl(D, var); - var->setAlignment(alignment.getQuantity()); + var->setAlignment(alignment.getAsAlign()); if (D.hasAttr()) CGM.AddGlobalAnnotations(&D, var); @@ -1112,11 +1112,11 @@ Address CodeGenModule::createUnnamedGlobalFrom(const VarDecl &D, llvm::GlobalVariable *GV = new llvm::GlobalVariable( getModule(), Ty, isConstant, llvm::GlobalValue::PrivateLinkage, Constant, Name, InsertBefore, llvm::GlobalValue::NotThreadLocal, AS); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); CacheEntry = GV; } else if (CacheEntry->getAlignment() < Align.getQuantity()) { - CacheEntry->setAlignment(Align.getQuantity()); + CacheEntry->setAlignment(Align.getAsAlign()); } return Address(CacheEntry, Align); @@ -2395,7 +2395,7 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, ParamValue Arg, // Don't push a cleanup in a thunk for a method that will also emit a // cleanup. if (hasAggregateEvaluationKind(Ty) && !CurFuncIsThunk && - Ty->getAs()->getDecl()->isParamDestroyedInCallee()) { + Ty->castAs()->getDecl()->isParamDestroyedInCallee()) { if (QualType::DestructionKind DtorKind = D.needsDestruction(getContext())) { assert((DtorKind == QualType::DK_cxx_destructor || diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 36015c21915c..776d21f4ea96 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -66,7 +66,7 @@ Address CodeGenFunction::CreateTempAllocaWithoutCast(llvm::Type *Ty, const Twine &Name, llvm::Value *ArraySize) { auto Alloca = CreateTempAlloca(Ty, Name, ArraySize); - Alloca->setAlignment(llvm::MaybeAlign(Align.getQuantity())); + Alloca->setAlignment(Align.getAsAlign()); return Address(Alloca, Align); } @@ -126,7 +126,7 @@ Address CodeGenFunction::CreateDefaultAlignTempAlloca(llvm::Type *Ty, void CodeGenFunction::InitTempAlloca(Address Var, llvm::Value *Init) { assert(isa(Var.getPointer())); auto *Store = new llvm::StoreInst(Init, Var.getPointer()); - Store->setAlignment(Var.getAlignment().getQuantity()); + Store->setAlignment(Var.getAlignment().getAsAlign()); llvm::BasicBlock *Block = AllocaInsertPt->getParent(); Block->getInstList().insertAfter(AllocaInsertPt->getIterator(), Store); } @@ -392,7 +392,7 @@ static Address createReferenceTemporary(CodeGenFunction &CGF, llvm::GlobalValue::NotThreadLocal, CGF.getContext().getTargetAddressSpace(AS)); CharUnits alignment = CGF.getContext().getTypeAlignInChars(Ty); - GV->setAlignment(alignment.getQuantity()); + GV->setAlignment(alignment.getAsAlign()); llvm::Constant *C = GV; if (AS != LangAS::Default) C = TCG.performAddrSpaceCast( diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 9610a04be343..ab51512ef98c 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -501,7 +501,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType, CGM.getContext().getTargetAddressSpace(AS)); Emitter.finalize(GV); CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GV, ArrayQTy, Align)); return; } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 9057d1605943..49527e9691a7 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -418,13 +418,10 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, const Expr *BaseExpr = BO->getLHS(); const Expr *MemFnExpr = BO->getRHS(); - const MemberPointerType *MPT = - MemFnExpr->getType()->castAs(); - - const FunctionProtoType *FPT = - MPT->getPointeeType()->castAs(); - const CXXRecordDecl *RD = - cast(MPT->getClass()->getAs()->getDecl()); + const auto *MPT = MemFnExpr->getType()->castAs(); + const auto *FPT = MPT->getPointeeType()->castAs(); + const auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); // Emit the 'this' pointer. Address This = Address::invalid(); @@ -535,7 +532,7 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF, CharUnits Align = std::max(Layout.getNonVirtualAlignment(), DestPtr.getAlignment()); - NullVariable->setAlignment(Align.getQuantity()); + NullVariable->setAlignment(Align.getAsAlign()); Address SrcPtr = Address(CGF.EmitCastToVoidPtr(NullVariable), Align); diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 31cf2aef1ba0..03ef4ab18422 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -659,7 +659,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter, } bool ConstStructBuilder::Build(InitListExpr *ILE, bool AllowOverwrite) { - RecordDecl *RD = ILE->getType()->getAs()->getDecl(); + RecordDecl *RD = ILE->getType()->castAs()->getDecl(); const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); unsigned FieldNo = -1; @@ -839,7 +839,7 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD, } llvm::Constant *ConstStructBuilder::Finalize(QualType Type) { - RecordDecl *RD = Type->getAs()->getDecl(); + RecordDecl *RD = Type->castAs()->getDecl(); llvm::Type *ValTy = CGM.getTypes().ConvertType(Type); return Builder.build(ValTy, RD->hasFlexibleArrayMember()); } @@ -907,7 +907,7 @@ static ConstantAddress tryEmitGlobalCompoundLiteral(CodeGenModule &CGM, llvm::GlobalVariable::NotThreadLocal, CGM.getContext().getTargetAddressSpace(addressSpace)); emitter.finalize(GV); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); CGM.setAddrOfConstantCompoundLiteral(E, GV); return ConstantAddress(GV, Align); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 4676be40768f..bff88b2feca2 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -2662,7 +2662,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { case OffsetOfNode::Field: { FieldDecl *MemberDecl = ON.getField(); - RecordDecl *RD = CurrentType->getAs()->getDecl(); + RecordDecl *RD = CurrentType->castAs()->getDecl(); const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); // Compute the index of the field in its parent. @@ -2695,7 +2695,7 @@ Value *ScalarExprEmitter::VisitOffsetOfExpr(OffsetOfExpr *E) { continue; } - RecordDecl *RD = CurrentType->getAs()->getDecl(); + RecordDecl *RD = CurrentType->castAs()->getDecl(); const ASTRecordLayout &RL = CGF.getContext().getASTRecordLayout(RD); // Save the element type. diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index ee0fd184c64d..c21f257442c9 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -1294,7 +1294,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { // Emit a placeholder symbol. GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false, llvm::GlobalValue::ExternalLinkage, nullptr, Name); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); + GV->setAlignment(CGM.getPointerAlign().getAsAlign()); } return llvm::ConstantExpr::getBitCast(GV, ProtocolPtrTy); } @@ -1318,7 +1318,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { llvm::ConstantExpr::getBitCast(Protocol, ProtocolPtrTy), RefName); GV->setComdat(TheModule.getOrInsertComdat(RefName)); GV->setSection(sectionName()); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); + GV->setAlignment(CGM.getPointerAlign().getAsAlign()); Ref = GV; } EmittedProtocolRef = true; @@ -1497,7 +1497,7 @@ class CGObjCGNUstep2 : public CGObjCGNUstep { Sym->setSection((Section + SecSuffix).str()); Sym->setComdat(TheModule.getOrInsertComdat((Prefix + Section).str())); - Sym->setAlignment(CGM.getPointerAlign().getQuantity()); + Sym->setAlignment(CGM.getPointerAlign().getAsAlign()); return Sym; }; return { Sym("__start_", "$a"), Sym("__stop", "$z") }; @@ -4087,7 +4087,7 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF, auto GV = new llvm::GlobalVariable(TheModule, IntTy, false, llvm::GlobalValue::LinkOnceAnyLinkage, llvm::Constant::getNullValue(IntTy), name); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); Offset = GV; } Offset = CGF.Builder.CreateAlignedLoad(Offset, Align); diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 12880fecbadf..8e28b2f05c16 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2018,7 +2018,7 @@ CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); // Don't enforce the target's minimum global alignment, since the only use // of the string is via this class initializer. - GV->setAlignment(1); + GV->setAlignment(llvm::Align::None()); Fields.addBitCast(GV, CGM.Int8PtrTy); // String length. @@ -2517,14 +2517,12 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, } if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - const ConstantArrayType *CArray = - dyn_cast_or_null(Array); + auto *CArray = cast(Array); uint64_t ElCount = CArray->getSize().getZExtValue(); assert(CArray && "only array with known element size is supported"); FQT = CArray->getElementType(); while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { - const ConstantArrayType *CArray = - dyn_cast_or_null(Array); + auto *CArray = cast(Array); ElCount *= CArray->getSize().getZExtValue(); FQT = CArray->getElementType(); } @@ -3103,7 +3101,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { nullptr, "OBJC_PROTOCOL_" + PD->getName()); Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); // FIXME: Is this necessary? Why only for protocol? - Entry->setAlignment(4); + Entry->setAlignment(llvm::Align(4)); } return Entry; @@ -3609,7 +3607,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { "Forward metaclass reference has incorrect type."); values.finishAndSetAsInitializer(GV); GV->setSection(Section); - GV->setAlignment(CGM.getPointerAlign().getQuantity()); + GV->setAlignment(CGM.getPointerAlign().getAsAlign()); CGM.addCompilerUsedGlobal(GV); } else GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true); @@ -4016,7 +4014,7 @@ llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name); if (!Section.empty()) GV->setSection(Section); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); if (AddToUsed) CGM.addCompilerUsedGlobal(GV); return GV; @@ -4064,7 +4062,7 @@ CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type, if (CGM.getTriple().isOSBinFormatMachO()) GV->setSection(Section); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); - GV->setAlignment(CharUnits::One().getQuantity()); + GV->setAlignment(CharUnits::One().getAsAlign()); CGM.addCompilerUsedGlobal(GV); return GV; @@ -4902,7 +4900,7 @@ LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { const ObjCInterfaceDecl *ID = - ObjectTy->getAs()->getInterface(); + ObjectTy->castAs()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } @@ -6076,7 +6074,8 @@ void CGObjCNonFragileABIMac::AddModuleClassList( llvm::GlobalVariable *GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, LT, Init, SymbolName); - GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); + GV->setAlignment( + llvm::Align(CGM.getDataLayout().getABITypeAlignment(Init->getType()))); GV->setSection(SectionName); CGM.addCompilerUsedGlobal(GV); } @@ -6319,8 +6318,8 @@ CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, if (CGM.getTriple().isOSBinFormatMachO()) GV->setSection("__DATA, __objc_data"); - GV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)); + GV->setAlignment(llvm::Align( + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy))); if (!CGM.getTriple().isOSBinFormatCOFF()) if (HiddenVisibility) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); @@ -6527,7 +6526,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, PTGV->setSection(GetSectionName("__objc_protorefs", "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - PTGV->setAlignment(Align.getQuantity()); + PTGV->setAlignment(Align.getAsAlign()); if (!CGM.getTriple().isOSBinFormatMachO()) PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName)); CGM.addUsedGlobal(PTGV); @@ -6759,8 +6758,8 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar); IvarOffsetGV->setInitializer( llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset)); - IvarOffsetGV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)); + IvarOffsetGV->setAlignment(llvm::Align( + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy))); if (!CGM.getTriple().isOSBinFormatCOFF()) { // FIXME: This matches gcc, but shouldn't the visibility be set on the use @@ -6986,8 +6985,8 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( ProtocolRef); if (!CGM.getTriple().isOSBinFormatMachO()) PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef)); - PTGV->setAlignment( - CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); + PTGV->setAlignment(llvm::Align( + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy))); PTGV->setSection(GetSectionName("__objc_protolist", "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); @@ -7053,7 +7052,7 @@ LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { - ObjCInterfaceDecl *ID = ObjectTy->getAs()->getInterface(); + ObjCInterfaceDecl *ID = ObjectTy->castAs()->getInterface(); llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, Offset); @@ -7338,7 +7337,7 @@ CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, CGM.getModule(), ClassGV->getType(), false, getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, "OBJC_CLASSLIST_REFERENCES_$_"); - Entry->setAlignment(CGF.getPointerAlign().getQuantity()); + Entry->setAlignment(CGF.getPointerAlign().getAsAlign()); if (!ID || !ID->hasAttr()) Entry->setSection(SectionName); @@ -7377,7 +7376,7 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, CGM.getModule(), ClassGV->getType(), false, getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); - Entry->setAlignment(CGF.getPointerAlign().getQuantity()); + Entry->setAlignment(CGF.getPointerAlign().getAsAlign()); Entry->setSection(SectionName); CGM.addCompilerUsedGlobal(Entry); } @@ -7401,7 +7400,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, getLinkageTypeForObjCMetadata(CGM, SectionName), MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_"); - Entry->setAlignment(Align.getQuantity()); + Entry->setAlignment(Align.getAsAlign()); Entry->setSection(SectionName); CGM.addCompilerUsedGlobal(Entry); } @@ -7500,7 +7499,7 @@ Address CGObjCNonFragileABIMac::EmitSelectorAddr(CodeGenFunction &CGF, "OBJC_SELECTOR_REFERENCES_"); Entry->setExternallyInitialized(true); Entry->setSection(SectionName); - Entry->setAlignment(Align.getQuantity()); + Entry->setAlignment(Align.getAsAlign()); CGM.addCompilerUsedGlobal(Entry); } @@ -7733,7 +7732,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, : llvm::GlobalValue::WeakAnyLinkage; if (Entry) { values.finishAndSetAsInitializer(Entry); - Entry->setAlignment(CGM.getPointerAlign().getQuantity()); + Entry->setAlignment(CGM.getPointerAlign().getAsAlign()); } else { Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName, CGM.getPointerAlign(), diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 4da84f230ec1..27231dbf9b3c 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -2868,7 +2868,8 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Addr, bool PerformInit) { - if (CGM.getLangOpts().OMPTargetTriples.empty()) + if (CGM.getLangOpts().OMPTargetTriples.empty() && + !CGM.getLangOpts().OpenMPIsDevice) return false; Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); @@ -4201,7 +4202,9 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { llvm::Module &M = CGM.getModule(); llvm::LLVMContext &C = M.getContext(); - SmallVector + SmallVector, + 16> OrderedEntries(OffloadEntriesInfoManager.size()); llvm::SmallVector ParentFunctions( OffloadEntriesInfoManager.size()); @@ -4219,7 +4222,8 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { // Create function that emits metadata for each target region entry; auto &&TargetRegionMetadataEmitter = - [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString]( + [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, + &GetMDString]( unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned Line, const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { @@ -4237,8 +4241,19 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { GetMDInt(FileID), GetMDString(ParentName), GetMDInt(Line), GetMDInt(E.getOrder())}; + SourceLocation Loc; + for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), + E = CGM.getContext().getSourceManager().fileinfo_end(); + I != E; ++I) { + if (I->getFirst()->getUniqueID().getDevice() == DeviceID && + I->getFirst()->getUniqueID().getFile() == FileID) { + Loc = CGM.getContext().getSourceManager().translateFileLineCol( + I->getFirst(), Line, 1); + break; + } + } // Save this entry in the right position of the ordered entries array. - OrderedEntries[E.getOrder()] = &E; + OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); ParentFunctions[E.getOrder()] = ParentName; // Add metadata to the named metadata node. @@ -4266,7 +4281,8 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; // Save this entry in the right position of the ordered entries array. - OrderedEntries[E.getOrder()] = &E; + OrderedEntries[E.getOrder()] = + std::make_tuple(&E, SourceLocation(), MangledName); // Add metadata to the named metadata node. MD->addOperand(llvm::MDNode::get(C, Ops)); @@ -4275,11 +4291,11 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( DeviceGlobalVarMetadataEmitter); - for (const auto *E : OrderedEntries) { - assert(E && "All ordered entries must exist!"); + for (const auto &E : OrderedEntries) { + assert(std::get<0>(E) && "All ordered entries must exist!"); if (const auto *CE = dyn_cast( - E)) { + std::get<0>(E))) { if (!CE->getID() || !CE->getAddress()) { // Do not blame the entry if the parent funtion is not emitted. StringRef FnName = ParentFunctions[CE->getOrder()]; @@ -4287,16 +4303,16 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { continue; unsigned DiagID = CGM.getDiags().getCustomDiagID( DiagnosticsEngine::Error, - "Offloading entry for target region is incorrect: either the " + "Offloading entry for target region in %0 is incorrect: either the " "address or the ID is invalid."); - CGM.getDiags().Report(DiagID); + CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; continue; } createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); - } else if (const auto *CE = - dyn_cast(E)) { + } else if (const auto *CE = dyn_cast( + std::get<0>(E))) { OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = static_cast( CE->getFlags()); @@ -4307,10 +4323,10 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { continue; if (!CE->getAddress()) { unsigned DiagID = CGM.getDiags().getCustomDiagID( - DiagnosticsEngine::Error, - "Offloading entry for declare target variable is incorrect: the " - "address is invalid."); - CGM.getDiags().Report(DiagID); + DiagnosticsEngine::Error, "Offloading entry for declare target " + "variable %0 is incorrect: the " + "address is invalid."); + CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); continue; } // The vaiable has no definition - no need to add the entry. @@ -9791,7 +9807,8 @@ CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, llvm::Constant *Addr) { - if (CGM.getLangOpts().OMPTargetTriples.empty()) + if (CGM.getLangOpts().OMPTargetTriples.empty() && + !CGM.getLangOpts().OpenMPIsDevice) return; llvm::Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); diff --git a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index c6c595dcc2c6..746852485bab 100644 --- a/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -4730,7 +4730,7 @@ Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF, /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, CGM.getContext().getTargetAddressSpace(LangAS::cuda_constant)); CharUnits Align = CGM.getContext().getDeclAlign(VD); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); return Address(GV, Align); } case OMPAllocateDeclAttr::OMPPTeamMemAlloc: { @@ -4742,7 +4742,7 @@ Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF, /*InsertBefore=*/nullptr, llvm::GlobalValue::NotThreadLocal, CGM.getContext().getTargetAddressSpace(LangAS::cuda_shared)); CharUnits Align = CGM.getContext().getDeclAlign(VD); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); return Address(GV, Align); } case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: @@ -4753,7 +4753,7 @@ Address CGOpenMPRuntimeNVPTX::getAddressOfLocalVariable(CodeGenFunction &CGF, llvm::GlobalValue::InternalLinkage, llvm::Constant::getNullValue(VarTy), VD->getName()); CharUnits Align = CGM.getContext().getDeclAlign(VD); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); return Address(GV, Align); } } diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index b2522cbc8ae8..e934ab34a3a2 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -1671,7 +1671,7 @@ CodeGenFunction::EmitNullInitialization(Address DestPtr, QualType Ty) { llvm::GlobalVariable::PrivateLinkage, NullConstant, Twine()); CharUnits NullAlign = DestPtr.getAlignment(); - NullVariable->setAlignment(NullAlign.getQuantity()); + NullVariable->setAlignment(NullAlign.getAsAlign()); Address SrcPtr(Builder.CreateBitCast(NullVariable, Builder.getInt8PtrTy()), NullAlign); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c3060d1fb351..02007ab28abb 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1034,7 +1034,7 @@ class CodeGenFunction : public CodeGenTypeCache { assert(isInConditionalBranch()); llvm::BasicBlock *block = OutermostConditional->getStartingBlock(); auto store = new llvm::StoreInst(value, addr.getPointer(), &block->back()); - store->setAlignment(addr.getAlignment().getQuantity()); + store->setAlignment(addr.getAlignment().getAsAlign()); } /// An RAII object to record that we're evaluating a statement diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 5d1a3d556d20..f8b4ffa024f2 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -1182,7 +1182,7 @@ void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { // The LTO linker doesn't seem to like it when we set an alignment // on appending variables. Take it off as a workaround. - list->setAlignment(0); + list->setAlignment(llvm::None); Fns.clear(); } @@ -1596,11 +1596,11 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, unsigned alignment = D->getMaxAlignment() / Context.getCharWidth(); if (alignment) - F->setAlignment(alignment); + F->setAlignment(llvm::Align(alignment)); if (!D->hasAttr()) if (LangOpts.FunctionAlignment) - F->setAlignment(1 << LangOpts.FunctionAlignment); + F->setAlignment(llvm::Align(1ull << LangOpts.FunctionAlignment)); // Some C++ ABIs require 2-byte alignment for member functions, in order to // reserve a bit for differentiating between virtual and non-virtual member @@ -1608,7 +1608,7 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, // member function, set its alignment accordingly. if (getTarget().getCXXABI().areMemberFunctionsAligned()) { if (F->getAlignment() < 2 && isa(D)) - F->setAlignment(2); + F->setAlignment(llvm::Align(2)); } // In the cross-dso CFI mode with canonical jump tables, we want !type @@ -3448,7 +3448,7 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName, // handling. GV->setConstant(isTypeConstant(D->getType(), false)); - GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); + GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); setLinkageForGV(GV, D); @@ -3598,7 +3598,7 @@ llvm::GlobalVariable *CodeGenModule::CreateOrReplaceCXXRuntimeVariable( !GV->hasAvailableExternallyLinkage()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); - GV->setAlignment(Alignment); + GV->setAlignment(llvm::MaybeAlign(Alignment)); return GV; } @@ -3994,8 +3994,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, GV->setConstant(true); } - GV->setAlignment(getContext().getDeclAlign(D).getQuantity()); - + GV->setAlignment(getContext().getDeclAlign(D).getAsAlign()); // On Darwin, if the normal linkage of a C++ thread_local variable is // LinkOnce or Weak, we keep the normal linkage to prevent multiple @@ -4694,7 +4693,7 @@ CodeGenModule::GetAddrOfConstantCFString(const StringLiteral *Literal) { // of the string is via this class initializer. CharUnits Align = isUTF16 ? Context.getTypeAlignInChars(Context.ShortTy) : Context.getTypeAlignInChars(Context.CharTy); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); // FIXME: We set the section explicitly to avoid a bug in ld64 224.1. // Without it LLVM can merge the string with a non unnamed_addr one during @@ -4847,7 +4846,7 @@ GenerateStringLiteral(llvm::Constant *C, llvm::GlobalValue::LinkageTypes LT, auto *GV = new llvm::GlobalVariable( M, C->getType(), !CGM.getLangOpts().WritableStrings, LT, C, GlobalName, nullptr, llvm::GlobalVariable::NotThreadLocal, AddrSpace); - GV->setAlignment(Alignment.getQuantity()); + GV->setAlignment(Alignment.getAsAlign()); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); if (GV->isWeakForLinker()) { assert(CGM.supportsCOMDAT() && "Only COFF uses weak string literals"); @@ -4871,7 +4870,7 @@ CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S, Entry = &ConstantStringMap[C]; if (auto GV = *Entry) { if (Alignment.getQuantity() > GV->getAlignment()) - GV->setAlignment(Alignment.getQuantity()); + GV->setAlignment(Alignment.getAsAlign()); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), Alignment); } @@ -4934,7 +4933,7 @@ ConstantAddress CodeGenModule::GetAddrOfConstantCString( Entry = &ConstantStringMap[C]; if (auto GV = *Entry) { if (Alignment.getQuantity() > GV->getAlignment()) - GV->setAlignment(Alignment.getQuantity()); + GV->setAlignment(Alignment.getAsAlign()); return ConstantAddress(castStringLiteralToDefaultAddressSpace(*this, GV), Alignment); } @@ -5037,7 +5036,7 @@ ConstantAddress CodeGenModule::GetAddrOfGlobalTemporary( /*InsertBefore=*/nullptr, llvm::GlobalVariable::NotThreadLocal, TargetAS); if (emitter) emitter->finalize(GV); setGVProperties(GV, VD); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); if (supportsCOMDAT() && GV->isWeakForLinker()) GV->setComdat(TheModule.getOrInsertComdat(GV->getName())); if (VD->getTLSKind()) diff --git a/lib/CodeGen/CodeGenPGO.h b/lib/CodeGen/CodeGenPGO.h index 2e740f789243..a3778b549910 100644 --- a/lib/CodeGen/CodeGenPGO.h +++ b/lib/CodeGen/CodeGenPGO.h @@ -41,8 +41,8 @@ class CodeGenPGO { public: CodeGenPGO(CodeGenModule &CGM) - : CGM(CGM), NumValueSites({{0}}), NumRegionCounters(0), FunctionHash(0), - CurrentRegionCount(0) {} + : CGM(CGM), FuncNameVar(nullptr), NumValueSites({{0}}), + NumRegionCounters(0), FunctionHash(0), CurrentRegionCount(0) {} /// Whether or not we have PGO region data for the current function. This is /// false both when we have no data at all and when our data has been diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index ec27d4b045e9..a458811d7a30 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -135,8 +135,8 @@ isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT, // the class. if (const CXXRecordDecl *CRD = dyn_cast(RD)) { for (const auto &I : CRD->bases()) - if (!isSafeToConvert(I.getType()->getAs()->getDecl(), - CGT, AlreadyChecked)) + if (!isSafeToConvert(I.getType()->castAs()->getDecl(), CGT, + AlreadyChecked)) return false; } @@ -744,8 +744,7 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { if (const CXXRecordDecl *CRD = dyn_cast(RD)) { for (const auto &I : CRD->bases()) { if (I.isVirtual()) continue; - - ConvertRecordDeclType(I.getType()->getAs()->getDecl()); + ConvertRecordDeclType(I.getType()->castAs()->getDecl()); } } diff --git a/lib/CodeGen/ConstantInitBuilder.cpp b/lib/CodeGen/ConstantInitBuilder.cpp index 40b1607b5626..2d63d88020be 100644 --- a/lib/CodeGen/ConstantInitBuilder.cpp +++ b/lib/CodeGen/ConstantInitBuilder.cpp @@ -79,7 +79,7 @@ ConstantInitBuilderBase::createGlobal(llvm::Constant *initializer, /*insert before*/ nullptr, llvm::GlobalValue::NotThreadLocal, addressSpace); - GV->setAlignment(alignment.getQuantity()); + GV->setAlignment(alignment.getAsAlign()); resolveSelfReferences(GV); return GV; } diff --git a/lib/CodeGen/CoverageMappingGen.cpp b/lib/CodeGen/CoverageMappingGen.cpp index 6d18027f16a8..0a7a4fe33ac2 100644 --- a/lib/CodeGen/CoverageMappingGen.cpp +++ b/lib/CodeGen/CoverageMappingGen.cpp @@ -1442,7 +1442,7 @@ void CoverageMappingModuleGen::emit() { CovDataVal, llvm::getCoverageMappingVarName()); CovData->setSection(getCoverageSection(CGM)); - CovData->setAlignment(8); + CovData->setAlignment(llvm::Align(8)); // Make sure the data doesn't get deleted. CGM.addUsedGlobal(CovData); diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index e5eed43d3887..2945dec0bd7d 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -580,8 +580,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer( const FunctionProtoType *FPT = MPT->getPointeeType()->getAs(); - const CXXRecordDecl *RD = - cast(MPT->getClass()->getAs()->getDecl()); + auto *RD = + cast(MPT->getClass()->castAs()->getDecl()); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( CGM.getTypes().arrangeCXXMethodType(RD, FPT, /*FD=*/nullptr)); @@ -1143,7 +1143,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // Grab the vtable pointer as an intptr_t*. auto *ClassDecl = - cast(ElementType->getAs()->getDecl()); + cast(ElementType->castAs()->getDecl()); llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.IntPtrTy->getPointerTo(), ClassDecl); @@ -1346,7 +1346,7 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy) { auto *ClassDecl = - cast(SrcRecordTy->getAs()->getDecl()); + cast(SrcRecordTy->castAs()->getDecl()); llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo(), ClassDecl); @@ -1412,7 +1412,7 @@ llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Type *DestLTy = CGF.ConvertType(DestTy); auto *ClassDecl = - cast(SrcRecordTy->getAs()->getDecl()); + cast(SrcRecordTy->castAs()->getDecl()); // Get the vtable pointer. llvm::Value *VTable = CGF.GetVTablePtr(ThisAddr, PtrDiffLTy->getPointerTo(), ClassDecl); @@ -2194,7 +2194,7 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, guard->setVisibility(var->getVisibility()); // If the variable is thread-local, so is its guard variable. guard->setThreadLocalMode(var->getThreadLocalMode()); - guard->setAlignment(guardAlignment.getQuantity()); + guard->setAlignment(guardAlignment.getAsAlign()); // The ABI says: "It is suggested that it be emitted in the same COMDAT // group as the associated data object." In practice, this doesn't work for @@ -2547,7 +2547,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs( Guard->setThreadLocal(true); CharUnits GuardAlign = CharUnits::One(); - Guard->setAlignment(GuardAlign.getQuantity()); + Guard->setAlignment(GuardAlign.getAsAlign()); CodeGenFunction(CGM).GenerateCXXGlobalInitFunc( InitFunc, OrderedInits, ConstantAddress(Guard, GuardAlign)); @@ -3100,8 +3100,8 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { return false; // Check that the class is dynamic iff the base is. - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); + auto *BaseDecl = + cast(Base->getType()->castAs()->getDecl()); if (!BaseDecl->isEmpty() && BaseDecl->isDynamicClass() != RD->isDynamicClass()) return false; @@ -3479,7 +3479,7 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo( CharUnits Align = CGM.getContext().toCharUnitsFromBits(CGM.getTarget().getPointerAlign(0)); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); // The Itanium ABI specifies that type_info objects must be globally // unique, with one exception: if the type is an incomplete class @@ -3564,8 +3564,8 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, unsigned Flags = 0; - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); + auto *BaseDecl = + cast(Base->getType()->castAs()->getDecl()); if (Base->isVirtual()) { // Mark the virtual base as seen. @@ -3663,8 +3663,8 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { // The __base_type member points to the RTTI for the base type. Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType())); - const CXXRecordDecl *BaseDecl = - cast(Base.getType()->getAs()->getDecl()); + auto *BaseDecl = + cast(Base.getType()->castAs()->getDecl()); int64_t OffsetFlags = 0; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index d1cd1b59fcd6..8a5ea844c21f 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -2355,7 +2355,7 @@ static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) { /*isConstant=*/false, llvm::GlobalVariable::ExternalLinkage, /*Initializer=*/nullptr, VarName, /*InsertBefore=*/nullptr, llvm::GlobalVariable::GeneralDynamicTLSModel); - GV->setAlignment(Align.getQuantity()); + GV->setAlignment(Align.getAsAlign()); return ConstantAddress(GV, Align); } @@ -2498,7 +2498,7 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, GV->getLinkage(), Zero, GuardName.str()); GuardVar->setVisibility(GV->getVisibility()); GuardVar->setDLLStorageClass(GV->getDLLStorageClass()); - GuardVar->setAlignment(GuardAlign.getQuantity()); + GuardVar->setAlignment(GuardAlign.getAsAlign()); if (GuardVar->isWeakForLinker()) GuardVar->setComdat( CGM.getModule().getOrInsertComdat(GuardVar->getName())); diff --git a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp index 84912954f72c..284e8022a3c4 100644 --- a/lib/CodeGen/ObjectFilePCHContainerOperations.cpp +++ b/lib/CodeGen/ObjectFilePCHContainerOperations.cpp @@ -279,7 +279,7 @@ class PCHContainerGenerator : public ASTConsumer { *M, Ty, /*constant*/ true, llvm::GlobalVariable::InternalLinkage, Data, "__clang_ast"); // The on-disk hashtable needs to be aligned. - ASTSym->setAlignment(8); + ASTSym->setAlignment(llvm::Align(8)); // Mach-O also needs a segment name. if (Triple.isOSBinFormatMachO()) diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index f9cbf1e1c6c4..eb7fe1b410d4 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -2809,8 +2809,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, for (const auto &I : CXXRD->bases()) { assert(!I.isVirtual() && !I.getType()->isDependentType() && "Unexpected base class!"); - const CXXRecordDecl *Base = - cast(I.getType()->getAs()->getDecl()); + const auto *Base = + cast(I.getType()->castAs()->getDecl()); // Classify this field. // @@ -3071,8 +3071,8 @@ static bool BitsContainNoUserData(QualType Ty, unsigned StartBit, for (const auto &I : CXXRD->bases()) { assert(!I.isVirtual() && !I.getType()->isDependentType() && "Unexpected base class!"); - const CXXRecordDecl *Base = - cast(I.getType()->getAs()->getDecl()); + const auto *Base = + cast(I.getType()->castAs()->getDecl()); // If the base is after the span we care about, ignore it. unsigned BaseOffset = Context.toBits(Layout.getBaseClassOffset(Base)); diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 94d50d713c87..73b258331f79 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -2281,12 +2281,10 @@ class OffloadingActionBuilder final { return ABRT_Inactive; } - /// Append top level actions generated by the builder. Return true if errors - /// were found. + /// Append top level actions generated by the builder. virtual void appendTopLevelActions(ActionList &AL) {} - /// Append linker actions generated by the builder. Return true if errors - /// were found. + /// Append linker actions generated by the builder. virtual void appendLinkDependences(OffloadAction::DeviceDependences &DA) {} /// Initialize the builder. Return true if any initialization errors are @@ -2314,6 +2312,8 @@ class OffloadingActionBuilder final { /// compilation. bool CompileHostOnly = false; bool CompileDeviceOnly = false; + bool EmitLLVM = false; + bool EmitAsm = false; /// List of GPU architectures to use in this compilation. SmallVector GpuArchList; @@ -2329,6 +2329,10 @@ class OffloadingActionBuilder final { /// Flag for -fgpu-rdc. bool Relocatable = false; + + /// Default GPU architecture if there's no one specified. + CudaArch DefaultCudaArch = CudaArch::UNKNOWN; + public: CudaActionBuilderBase(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs, @@ -2480,6 +2484,8 @@ class OffloadingActionBuilder final { CompileDeviceOnly = PartialCompilationArg && PartialCompilationArg->getOption().matches( options::OPT_cuda_device_only); + EmitLLVM = Args.getLastArg(options::OPT_emit_llvm); + EmitAsm = Args.getLastArg(options::OPT_S); // Collect all cuda_gpu_arch parameters, removing duplicates. std::set GpuArchs; @@ -2516,7 +2522,7 @@ class OffloadingActionBuilder final { // supported GPUs. sm_20 code should work correctly, if // suboptimally, on all newer GPUs. if (GpuArchList.empty()) - GpuArchList.push_back(CudaArch::SM_20); + GpuArchList.push_back(DefaultCudaArch); return Error; } @@ -2528,7 +2534,9 @@ class OffloadingActionBuilder final { public: CudaActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) - : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) {} + : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_Cuda) { + DefaultCudaArch = CudaArch::SM_20; + } ActionBuilderReturnCode getDeviceDependences(OffloadAction::DeviceDependences &DA, @@ -2643,7 +2651,9 @@ class OffloadingActionBuilder final { public: HIPActionBuilder(Compilation &C, DerivedArgList &Args, const Driver::InputList &Inputs) - : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {} + : CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) { + DefaultCudaArch = CudaArch::GFX803; + } bool canUseBundlerUnbundler() const override { return true; } @@ -2666,7 +2676,8 @@ class OffloadingActionBuilder final { assert(!CompileHostOnly && "Not expecting CUDA actions in host-only compilation."); - if (!Relocatable && CurPhase == phases::Backend) { + if (!Relocatable && CurPhase == phases::Backend && !EmitLLVM && + !EmitAsm) { // If we are in backend phase, we attempt to generate the fat binary. // We compile each arch to IR and use a link action to generate code // object containing ISA. Then we use a special "link" action to create @@ -2734,7 +2745,8 @@ class OffloadingActionBuilder final { A = C.getDriver().ConstructPhaseAction(C, Args, CurPhase, A, AssociatedOffloadKind); - return ABRT_Success; + return (CompileDeviceOnly && CurPhase == FinalPhase) ? ABRT_Ignore_Host + : ABRT_Success; } void appendLinkDependences(OffloadAction::DeviceDependences &DA) override { diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index dd561cc0d892..5b267784ff1e 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -181,6 +181,20 @@ template <> struct ScalarEnumerationTraits { } }; +template <> +struct ScalarEnumerationTraits< + FormatStyle::BraceWrappingAfterControlStatementStyle> { + static void + enumeration(IO &IO, + FormatStyle::BraceWrappingAfterControlStatementStyle &Value) { + IO.enumCase(Value, "false", FormatStyle::BWACS_Never); + IO.enumCase(Value, "true", FormatStyle::BWACS_Always); + IO.enumCase(Value, "Never", FormatStyle::BWACS_Never); + IO.enumCase(Value, "MultiLine", FormatStyle::BWACS_MultiLine); + IO.enumCase(Value, "Always", FormatStyle::BWACS_Always); + } +}; + template <> struct ScalarEnumerationTraits { static void @@ -629,9 +643,12 @@ static FormatStyle expandPresets(const FormatStyle &Style) { if (Style.BreakBeforeBraces == FormatStyle::BS_Custom) return Style; FormatStyle Expanded = Style; - Expanded.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false, false, - false, true, true, true}; + Expanded.BraceWrapping = {false, false, FormatStyle::BWACS_Never, + false, false, false, + false, false, false, + false, false, false, + false, true, true, + true}; switch (Style.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -656,7 +673,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { case FormatStyle::BS_Allman: Expanded.BraceWrapping.AfterCaseLabel = true; Expanded.BraceWrapping.AfterClass = true; - Expanded.BraceWrapping.AfterControlStatement = true; + Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; Expanded.BraceWrapping.AfterEnum = true; Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterNamespace = true; @@ -670,7 +687,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) { case FormatStyle::BS_Whitesmiths: Expanded.BraceWrapping.AfterCaseLabel = true; Expanded.BraceWrapping.AfterClass = true; - Expanded.BraceWrapping.AfterControlStatement = true; + Expanded.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; Expanded.BraceWrapping.AfterEnum = true; Expanded.BraceWrapping.AfterFunction = true; Expanded.BraceWrapping.AfterNamespace = true; @@ -681,8 +698,12 @@ static FormatStyle expandPresets(const FormatStyle &Style) { Expanded.BraceWrapping.BeforeElse = true; break; case FormatStyle::BS_GNU: - Expanded.BraceWrapping = {true, true, true, true, true, true, true, true, - true, true, true, true, true, true, true, true}; + Expanded.BraceWrapping = {true, true, FormatStyle::BWACS_Always, + true, true, true, + true, true, true, + true, true, true, + true, true, true, + true}; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -722,9 +743,12 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None; LLVMStyle.BreakBeforeTernaryOperators = true; LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach; - LLVMStyle.BraceWrapping = {false, false, false, false, false, false, - false, false, false, false, false, false, - false, true, true, true}; + LLVMStyle.BraceWrapping = {false, false, FormatStyle::BWACS_Never, + false, false, false, + false, false, false, + false, false, false, + false, true, true, + true}; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; @@ -1067,7 +1091,7 @@ FormatStyle getMicrosoftStyle(FormatStyle::LanguageKind Language) { Style.UseTab = FormatStyle::UT_Never; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterClass = true; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; Style.BraceWrapping.AfterEnum = true; Style.BraceWrapping.AfterFunction = true; Style.BraceWrapping.AfterNamespace = true; diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp index df30f7db80e6..8b8d357d9cbe 100644 --- a/lib/Format/UnwrappedLineFormatter.cpp +++ b/lib/Format/UnwrappedLineFormatter.cpp @@ -306,8 +306,24 @@ class LineJoiner { } // Try to merge a control statement block with left brace wrapped if (I[1]->First->is(tok::l_brace) && - TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) { - return Style.BraceWrapping.AfterControlStatement + (TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, + tok::kw_switch, tok::kw_try, tok::kw_do) || + (TheLine->First->is(tok::r_brace) && TheLine->First->Next && + TheLine->First->Next->isOneOf(tok::kw_else, tok::kw_catch))) && + Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_MultiLine) { + // If possible, merge the next line's wrapped left brace with the current + // line. Otherwise, leave it on the next line, as this is a multi-line + // control statement. + return (Style.ColumnLimit == 0 || + TheLine->Last->TotalLength <= Style.ColumnLimit) + ? 1 + : 0; + } else if (I[1]->First->is(tok::l_brace) && + TheLine->First->isOneOf(tok::kw_if, tok::kw_while, + tok::kw_for)) { + return (Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always) ? tryMergeSimpleBlock(I, E, Limit) : 0; } @@ -410,7 +426,8 @@ class LineJoiner { SmallVectorImpl::const_iterator E, unsigned Limit) { if (Limit == 0) return 0; - if (Style.BraceWrapping.AfterControlStatement && + if (Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always && I[1]->First->is(tok::l_brace) && Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return 0; @@ -523,8 +540,9 @@ class LineJoiner { return 0; if (!Style.AllowShortIfStatementsOnASingleLine && Line.startsWith(tok::kw_if) && - Style.BraceWrapping.AfterControlStatement && I + 2 != E && - !I[2]->First->is(tok::r_brace)) + Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always && + I + 2 != E && !I[2]->First->is(tok::r_brace)) return 0; if (!Style.AllowShortLoopsOnASingleLine && Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) && @@ -533,8 +551,9 @@ class LineJoiner { return 0; if (!Style.AllowShortLoopsOnASingleLine && Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) && - Style.BraceWrapping.AfterControlStatement && I + 2 != E && - !I[2]->First->is(tok::r_brace)) + Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always && + I + 2 != E && !I[2]->First->is(tok::r_brace)) return 0; // FIXME: Consider an option to allow short exception handling clauses on // a single line. @@ -597,6 +616,17 @@ class LineJoiner { if (Tok->Next && Tok->Next->is(tok::kw_else)) return 0; + // Don't merge a trailing multi-line control statement block like: + // } else if (foo && + // bar) + // { <-- current Line + // baz(); + // } + if (Line.First == Line.Last && + Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_MultiLine) + return 0; + return 2; } } else if (I[1]->First->is(tok::l_brace)) { diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 8fd0e9433b63..bbe05602f6da 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -1167,7 +1167,8 @@ void UnwrappedLineParser::parseStructuralElement() { case tok::objc_autoreleasepool: nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BraceWrapping.AfterControlStatement) + if (Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always) addUnwrappedLine(); parseBlock(/*MustBeDeclaration=*/false); } @@ -1179,7 +1180,8 @@ void UnwrappedLineParser::parseStructuralElement() { // Skip synchronization object parseParens(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BraceWrapping.AfterControlStatement) + if (Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always) addUnwrappedLine(); parseBlock(/*MustBeDeclaration=*/false); } @@ -1989,7 +1991,8 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) { Style.BraceWrapping.IndentBraces); parseBlock(/*MustBeDeclaration=*/false); if (FormatTok->Tok.is(tok::kw_break)) { - if (Style.BraceWrapping.AfterControlStatement) + if (Style.BraceWrapping.AfterControlStatement == + FormatStyle::BWACS_Always) addUnwrappedLine(); parseStructuralElement(); } diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 95d9f62c6087..6a3c898d8c3e 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -543,6 +543,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, // C++20 features. if (LangOpts.CPlusPlus2a) { Builder.defineMacro("__cpp_conditional_explicit", "201806L"); + Builder.defineMacro("__cpp_constexpr_dynamic_alloc", "201907L"); Builder.defineMacro("__cpp_constinit", "201907L"); } if (LangOpts.Char8) diff --git a/lib/Frontend/Rewrite/RewriteModernObjC.cpp b/lib/Frontend/Rewrite/RewriteModernObjC.cpp index 563c7ca100ab..a11fed56fc34 100644 --- a/lib/Frontend/Rewrite/RewriteModernObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteModernObjC.cpp @@ -852,7 +852,7 @@ RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!isa(IvarT) && IvarT->isRecordType()) { - RecordDecl *RD = IvarT->getAs()->getDecl(); + RecordDecl *RD = IvarT->castAs()->getDecl(); RD = RD->getDefinition(); if (RD && !RD->getDeclName().getAsIdentifierInfo()) { // decltype(((Foo_IMPL*)0)->bar) * @@ -3637,7 +3637,7 @@ bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, return RewriteObjCFieldDeclType(ElemTy, Result); } else if (Type->isRecordType()) { - RecordDecl *RD = Type->getAs()->getDecl(); + RecordDecl *RD = Type->castAs()->getDecl(); if (RD->isCompleteDefinition()) { if (RD->isStruct()) Result += "\n\tstruct "; @@ -3727,15 +3727,15 @@ void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDec return; if (Type->isArrayType()) Type = Context->getBaseElementType(Type); - ObjCContainerDecl *IDecl = - dyn_cast(fieldDecl->getDeclContext()); + + auto *IDecl = dyn_cast(fieldDecl->getDeclContext()); TagDecl *TD = nullptr; if (Type->isRecordType()) { - TD = Type->getAs()->getDecl(); + TD = Type->castAs()->getDecl(); } else if (Type->isEnumeralType()) { - TD = Type->getAs()->getDecl(); + TD = Type->castAs()->getDecl(); } if (TD) { @@ -5753,7 +5753,7 @@ void RewriteModernObjC::HandleDeclInMainFile(Decl *D) { } } } else if (VD->getType()->isRecordType()) { - RecordDecl *RD = VD->getType()->getAs()->getDecl(); + RecordDecl *RD = VD->getType()->castAs()->getDecl(); if (RD->isCompleteDefinition()) RewriteRecordBody(RD); } @@ -7494,7 +7494,7 @@ Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); if (!isa(IvarT) && IvarT->isRecordType()) { - RecordDecl *RD = IvarT->getAs()->getDecl(); + RecordDecl *RD = IvarT->castAs()->getDecl(); RD = RD->getDefinition(); if (RD && !RD->getDeclName().getAsIdentifierInfo()) { // decltype(((Foo_IMPL*)0)->bar) * diff --git a/lib/Frontend/Rewrite/RewriteObjC.cpp b/lib/Frontend/Rewrite/RewriteObjC.cpp index e57a92683433..0fd0c7f50366 100644 --- a/lib/Frontend/Rewrite/RewriteObjC.cpp +++ b/lib/Frontend/Rewrite/RewriteObjC.cpp @@ -4849,7 +4849,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } } } else if (VD->getType()->isRecordType()) { - RecordDecl *RD = VD->getType()->getAs()->getDecl(); + RecordDecl *RD = VD->getType()->castAs()->getDecl(); if (RD->isCompleteDefinition()) RewriteRecordBody(RD); } diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 46c823816830..c7143fd41041 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -786,6 +786,31 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, LinModifiers, Steps, SourceRange(Loc, EndLoc)); } +/// Parse optional 'score' '(' ')' ':'. +static ExprResult parseContextScore(Parser &P) { + ExprResult ScoreExpr; + SmallString<16> Buffer; + StringRef SelectorName = + P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); + OMPDeclareVariantAttr::ScoreType ScoreKind = + OMPDeclareVariantAttr::ScoreUnknown; + (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind); + if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown) + return ScoreExpr; + assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified && + "Expected \"score\" clause."); + (void)P.ConsumeToken(); + SourceLocation RLoc; + ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); + // Parse ':' + if (P.getCurToken().is(tok::colon)) + (void)P.ConsumeAnyToken(); + else + P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon) + << "context selector score clause"; + return ScoreExpr; +} + /// Parse context selector for 'implementation' selector set: /// 'vendor' '(' ')' static void @@ -815,6 +840,7 @@ parseImplementationSelector(Parser &P, BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); (void)T.expectAndConsume(diag::err_expected_lparen_after, CtxSelectorName.data()); + Data.CtxScore = parseContextScore(P); // Parse . StringRef VendorName; if (Tok.is(tok::identifier)) { diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index b6fbbbff91f5..b20f279dcad2 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -1834,8 +1834,8 @@ Sema::AccessResult Sema::CheckBaseClassAccess(SourceLocation AccessLoc, return AR_accessible; CXXRecordDecl *BaseD, *DerivedD; - BaseD = cast(Base->getAs()->getDecl()); - DerivedD = cast(Derived->getAs()->getDecl()); + BaseD = cast(Base->castAs()->getDecl()); + DerivedD = cast(Derived->castAs()->getDecl()); AccessTarget Entity(Context, AccessTarget::Base, BaseD, DerivedD, Path.Access); diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index f2ab27fedd40..38c502d6b3f3 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -14509,7 +14509,7 @@ void Sema::RefersToMemberWithReducedAlignment( QualType BaseType = ME->getBase()->getType(); if (ME->isArrow()) BaseType = BaseType->getPointeeType(); - RecordDecl *RD = BaseType->getAs()->getDecl(); + RecordDecl *RD = BaseType->castAs()->getDecl(); if (RD->isInvalidDecl()) return; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7274fc96c5e8..9a0fb203533f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -7767,7 +7767,7 @@ struct FindOverriddenMethod { /// CXXRecordDecl::lookupInBases(). bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { RecordDecl *BaseRecord = - Specifier->getType()->getAs()->getDecl(); + Specifier->getType()->castAs()->getDecl(); DeclarationName Name = Method->getDeclName(); @@ -16560,7 +16560,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, else if (Context.getAsArrayType(FD->getType())) { QualType BaseType = Context.getBaseElementType(FD->getType()); if (BaseType->isRecordType() && - BaseType->getAs()->getDecl()->hasObjectMember()) + BaseType->castAs()->getDecl()->hasObjectMember()) Record->setHasObjectMember(true); else if (BaseType->isObjCObjectPointerType() || BaseType.isObjCGCStrong()) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index d31b48c122f8..812819c50ea7 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -547,7 +547,7 @@ static bool checkRecordDeclForAttr(const RecordDecl *RD) { // If it's type-dependent, we assume it could have the attribute. if (Ty.isDependentType()) return true; - return Ty.getAs()->getDecl()->hasAttr(); + return Ty.castAs()->getDecl()->hasAttr(); }, BPaths, true)) return true; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index eaeca7806d4b..986339815965 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2479,7 +2479,7 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class, } // If the base class is polymorphic or isn't empty, the new one is/isn't, too. - RecordDecl *BaseDecl = BaseType->getAs()->getDecl(); + RecordDecl *BaseDecl = BaseType->castAs()->getDecl(); assert(BaseDecl && "Record type has no declaration"); BaseDecl = BaseDecl->getDefinition(); assert(BaseDecl && "Base type is not incomplete, but has no definition"); @@ -8004,7 +8004,7 @@ struct FindHiddenVirtualMethod { /// to be used with CXXRecordDecl::lookupInBases(). bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) { RecordDecl *BaseRecord = - Specifier->getType()->getAs()->getDecl(); + Specifier->getType()->castAs()->getDecl(); DeclarationName Name = Method->getDeclName(); assert(Name.getNameKind() == DeclarationName::Identifier); @@ -11845,7 +11845,8 @@ buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T, const Type *E = T->getBaseElementTypeUnsafe(); bool NeedsCollectableMemCpy = - E->isRecordType() && E->getAs()->getDecl()->hasObjectMember(); + E->isRecordType() && + E->castAs()->getDecl()->hasObjectMember(); // Create a reference to the __builtin_objc_memmove_collectable function StringRef MemCpyName = NeedsCollectableMemCpy ? @@ -15535,8 +15536,8 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, return; for (const auto &I : RD->bases()) { - const CXXRecordDecl *Base = - cast(I.getType()->getAs()->getDecl()); + const auto *Base = + cast(I.getType()->castAs()->getDecl()); if (Base->getNumVBases() == 0) continue; MarkVirtualMembersReferenced(Loc, Base); diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index fd843e4a0608..0f3a27233eef 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -154,7 +154,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { ReturnValueOnError = false; } if (!(PointeeT->isRecordType() && - PointeeT->getAs()->isBeingDefined()) && + PointeeT->castAs()->isBeingDefined()) && RequireCompleteType(Range.getBegin(), PointeeT, DiagID, Kind, Range)) return ReturnValueOnError; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index dceef8152947..d75c8240a1c5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -13470,7 +13470,6 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, if (Input.isInvalid()) return ExprError(); resultType = Input.get()->getType(); - if (resultType->isDependentType()) break; // C99 6.5.3.3p1. We allow complex int and float as a GCC extension. @@ -13478,6 +13477,9 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc, // C99 does not support '~' for complex conjugation. Diag(OpLoc, diag::ext_integer_complement_complex) << resultType << Input.get()->getSourceRange(); + else if (Input.get()->IgnoreParenImpCasts()->getType()->isBooleanType()) + Diag(OpLoc, diag::warn_bitwise_negation_bool) + << FixItHint::CreateReplacement(OpLoc, "!"); else if (resultType->hasIntegerRepresentation()) break; else if (resultType->isExtVectorType() && Context.getLangOpts().OpenCL) { diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index a9efbbc9e5e2..a25e86b95c37 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -453,6 +453,9 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, 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)); } @@ -2457,8 +2460,8 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, // deallocation function's name is looked up in the global scope. LookupResult FoundDelete(*this, DeleteName, StartLoc, LookupOrdinaryName); if (AllocElemType->isRecordType() && DeleteScope != AFS_Global) { - CXXRecordDecl *RD - = cast(AllocElemType->getAs()->getDecl()); + auto *RD = + cast(AllocElemType->castAs()->getDecl()); LookupQualifiedName(FoundDelete, RD); } if (FoundDelete.isAmbiguous()) diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index e85499c0bbf0..87114a0fac63 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -1006,7 +1006,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // Rederive where we looked up. DeclContext *DC = (SS.isSet() ? computeDeclContext(SS, false) - : BaseType->getAs()->getDecl()); + : BaseType->castAs()->getDecl()); if (ExtraArgs) { ExprResult RetryExpr; diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index fdb8f488471f..a098450f5cda 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -2130,7 +2130,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R, /// Callback that looks for any member of a class with the given name. static bool LookupAnyMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name) { - RecordDecl *BaseRecord = Specifier->getType()->getAs()->getDecl(); + RecordDecl *BaseRecord = Specifier->getType()->castAs()->getDecl(); Path.Decls = BaseRecord->lookup(Name); return !Path.Decls.empty(); diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 42e1755b5862..2b659f7f11f9 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -5112,8 +5112,23 @@ void Sema::ActOnOpenMPDeclareVariantDirective( if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown || Data.Ctx == OMPDeclareVariantAttr::CtxUnknown) return; + Expr *Score = nullptr; + OMPDeclareVariantAttr::ScoreType ST = OMPDeclareVariantAttr::ScoreUnknown; + if (Data.CtxScore.isUsable()) { + ST = OMPDeclareVariantAttr::ScoreSpecified; + Score = Data.CtxScore.get(); + if (!Score->isTypeDependent() && !Score->isValueDependent() && + !Score->isInstantiationDependent() && + !Score->containsUnexpandedParameterPack()) { + llvm::APSInt Result; + ExprResult ICE = VerifyIntegerConstantExpression(Score, &Result); + if (ICE.isInvalid()) + return; + } + } auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit( - Context, VariantRef, Data.CtxSet, Data.Ctx, Data.ImplVendor, SR); + Context, VariantRef, Score, Data.CtxSet, ST, Data.Ctx, Data.ImplVendor, + SR); FD->addAttr(NewAttr); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index e189b5235a97..847a19baed14 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4922,9 +4922,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack()) NTTPType = NTTP->getExpansionType(ArgumentPackIndex); - // FIXME: Do we need to substitute into parameters here if they're - // instantiation-dependent but not dependent? - if (NTTPType->isDependentType() && + if (NTTPType->isInstantiationDependentType() && !isa(Template) && !Template->getDeclContext()->isDependentContext()) { // Do substitution on the type of the non-type template parameter. diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f6cf3696e1fd..881b4fd992e1 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -388,6 +388,10 @@ static void instantiateOMPDeclareVariantAttr( if (Expr *E = Attr.getVariantFuncRef()) VariantFuncRef = Subst(E); + ExprResult Score; + if (Expr *E = Attr.getScore()) + Score = Subst(E); + // Check function/variant ref. Optional> DeclVarData = S.checkOpenMPDeclareVariantFunction( @@ -395,8 +399,9 @@ static void instantiateOMPDeclareVariantAttr( if (!DeclVarData) return; // Instantiate the attribute. - Sema::OpenMPDeclareVariantCtsSelectorData Data( - Attr.getCtxSelectorSet(), Attr.getCtxSelector(), Attr.getImplVendor()); + Sema::OpenMPDeclareVariantCtsSelectorData Data(Attr.getCtxSelectorSet(), + Attr.getCtxSelector(), + Attr.getImplVendor(), Score); S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first, DeclVarData.getValue().second, Attr.getRange(), Data); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index a9459d97942f..3029e148dc10 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1955,7 +1955,8 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, QualifiedFunctionKind QFK) { // Does T refer to a function type with a cv-qualifier or a ref-qualifier? const FunctionProtoType *FPT = T->getAs(); - if (!FPT || (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) + if (!FPT || + (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) return false; S.Diag(Loc, diag::err_compound_qualified_function_type) @@ -1964,6 +1965,17 @@ static bool checkQualifiedFunction(Sema &S, QualType T, SourceLocation Loc, return true; } +bool Sema::CheckQualifiedFunctionForTypeId(QualType T, SourceLocation Loc) { + const FunctionProtoType *FPT = T->getAs(); + if (!FPT || + (FPT->getMethodQuals().empty() && FPT->getRefQualifier() == RQ_None)) + return false; + + Diag(Loc, diag::err_qualified_function_typeid) + << T << getFunctionQualifiersAsString(FPT); + return true; +} + /// Build a pointer type. /// /// \param T The type to which we'll be building a pointer. diff --git a/lib/Tooling/Refactoring/Stencil.cpp b/lib/Tooling/Refactoring/Stencil.cpp index 78239b96d3c8..f7687f91e494 100644 --- a/lib/Tooling/Refactoring/Stencil.cpp +++ b/lib/Tooling/Refactoring/Stencil.cpp @@ -24,6 +24,7 @@ using namespace clang; using namespace tooling; using ast_matchers::MatchFinder; +using ast_type_traits::DynTypedNode; using llvm::errc; using llvm::Error; using llvm::Expected; @@ -37,7 +38,7 @@ template const D *down_cast(const StencilPartInterface *P) { return static_cast(P); } -static llvm::Expected +static llvm::Expected getNode(const ast_matchers::BoundNodes &Nodes, StringRef Id) { auto &NodesMap = Nodes.getMap(); auto It = NodesMap.find(Id); @@ -60,6 +61,21 @@ struct DebugPrintNodeData { std::string Id; }; +// Operators that take a single node Id as an argument. +enum class UnaryNodeOperator { + Parens, + Deref, + Address, +}; + +// Generic container for stencil operations with a (single) node-id argument. +struct UnaryOperationData { + UnaryOperationData(UnaryNodeOperator Op, std::string Id) + : Op(Op), Id(std::move(Id)) {} + UnaryNodeOperator Op; + std::string Id; +}; + // The fragment of code corresponding to the selected range. struct SelectorData { explicit SelectorData(RangeSelector S) : Selector(std::move(S)) {} @@ -82,7 +98,6 @@ struct IfBoundData { StencilPart TruePart; StencilPart FalsePart; }; -} // namespace bool isEqualData(const RawTextData &A, const RawTextData &B) { return A.Text == B.Text; @@ -92,6 +107,10 @@ bool isEqualData(const DebugPrintNodeData &A, const DebugPrintNodeData &B) { return A.Id == B.Id; } +bool isEqualData(const UnaryOperationData &A, const UnaryOperationData &B) { + return A.Op == B.Op && A.Id == B.Id; +} + // Equality is not (yet) defined for \c RangeSelector. bool isEqualData(const SelectorData &, const SelectorData &) { return false; } @@ -131,6 +150,32 @@ Error evalData(const DebugPrintNodeData &Data, return Error::success(); } +Error evalData(const UnaryOperationData &Data, + const MatchFinder::MatchResult &Match, std::string *Result) { + const auto *E = Match.Nodes.getNodeAs(Data.Id); + if (E == nullptr) + return llvm::make_error( + errc::invalid_argument, "Id not bound or not Expr: " + Data.Id); + llvm::Optional Source; + switch (Data.Op) { + case UnaryNodeOperator::Parens: + Source = buildParens(*E, *Match.Context); + break; + case UnaryNodeOperator::Deref: + Source = buildDereference(*E, *Match.Context); + break; + case UnaryNodeOperator::Address: + Source = buildAddressOf(*E, *Match.Context); + break; + } + if (!Source) + return llvm::make_error( + errc::invalid_argument, + "Could not construct expression source from ID: " + Data.Id); + *Result += *Source; + return Error::success(); +} + Error evalData(const SelectorData &Data, const MatchFinder::MatchResult &Match, std::string *Result) { auto Range = Data.Selector(Match); @@ -203,6 +248,7 @@ class StencilPartImpl : public StencilPartInterface { return false; } }; +} // namespace StencilPart Stencil::wrap(StringRef Text) { return stencil::text(Text); @@ -239,6 +285,21 @@ StencilPart stencil::dPrint(StringRef Id) { return StencilPart(std::make_shared>(Id)); } +StencilPart stencil::expression(llvm::StringRef Id) { + return StencilPart(std::make_shared>( + UnaryNodeOperator::Parens, Id)); +} + +StencilPart stencil::deref(llvm::StringRef ExprId) { + return StencilPart(std::make_shared>( + UnaryNodeOperator::Deref, ExprId)); +} + +StencilPart stencil::addressOf(llvm::StringRef ExprId) { + return StencilPart(std::make_shared>( + UnaryNodeOperator::Address, ExprId)); +} + StencilPart stencil::access(StringRef BaseId, StencilPart Member) { return StencilPart( std::make_shared>(BaseId, std::move(Member))); diff --git a/test/Driver/arm-compiler-rt.c b/test/Driver/arm-compiler-rt.c index a7e947c37867..b1acd6d67363 100644 --- a/test/Driver/arm-compiler-rt.c +++ b/test/Driver/arm-compiler-rt.c @@ -1,21 +1,42 @@ -// RUN: %clang -target arm-linux-gnueabi -rtlib=compiler-rt -### %s 2>&1 | FileCheck %s -check-prefix ARM-GNUEABI +// RUN: %clang -target arm-linux-gnueabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-GNUEABI // ARM-GNUEABI: "{{.*[/\\]}}libclang_rt.builtins-arm.a" -// RUN: %clang -target arm-linux-gnueabi -rtlib=compiler-rt -mfloat-abi=hard -### %s 2>&1 | FileCheck %s -check-prefix ARM-GNUEABI-ABI +// RUN: %clang -target arm-linux-gnueabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -mfloat-abi=hard -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-GNUEABI-ABI // ARM-GNUEABI-ABI: "{{.*[/\\]}}libclang_rt.builtins-armhf.a" -// RUN: %clang -target arm-linux-gnueabihf -rtlib=compiler-rt -### %s 2>&1 | FileCheck %s -check-prefix ARM-GNUEABIHF +// RUN: %clang -target arm-linux-gnueabihf \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-GNUEABIHF // ARM-GNUEABIHF: "{{.*[/\\]}}libclang_rt.builtins-armhf.a" -// RUN: %clang -target arm-linux-gnueabihf -rtlib=compiler-rt -mfloat-abi=soft -### %s 2>&1 | FileCheck %s -check-prefix ARM-GNUEABIHF-ABI +// RUN: %clang -target arm-linux-gnueabihf \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -mfloat-abi=soft -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-GNUEABIHF-ABI // ARM-GNUEABIHF-ABI: "{{.*[/\\]}}libclang_rt.builtins-arm.a" -// RUN: %clang -target arm-windows-itanium -rtlib=compiler-rt -### %s 2>&1 | FileCheck %s -check-prefix ARM-WINDOWS +// RUN: %clang -target arm-windows-itanium \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-WINDOWS // ARM-WINDOWS: "{{.*[/\\]}}clang_rt.builtins-arm.lib" -// RUN: %clang -target arm-linux-androideabi -rtlib=compiler-rt -### %s 2>&1 | FileCheck %s -check-prefix ARM-ANDROID +// RUN: %clang -target arm-linux-androideabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-ANDROID // ARM-ANDROID: "{{.*[/\\]}}libclang_rt.builtins-arm-android.a" -// RUN: %clang -target arm-linux-androideabi -rtlib=compiler-rt -mfloat-abi=hard -### %s 2>&1 | FileCheck %s -check-prefix ARM-ANDROIDHF +// RUN: %clang -target arm-linux-androideabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: -rtlib=compiler-rt -mfloat-abi=hard -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix ARM-ANDROIDHF // ARM-ANDROIDHF: "{{.*[/\\]}}libclang_rt.builtins-armhf-android.a" diff --git a/test/Driver/hip-default-gpu-arch.hip b/test/Driver/hip-default-gpu-arch.hip new file mode 100644 index 000000000000..56e36882dc63 --- /dev/null +++ b/test/Driver/hip-default-gpu-arch.hip @@ -0,0 +1,7 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// RUN: %clang -### -x hip -c %s 2>&1 | FileCheck %s + +// CHECK: {{.*}}clang{{.*}}"-target-cpu" "gfx803" diff --git a/test/Driver/hip-device-compile.hip b/test/Driver/hip-device-compile.hip new file mode 100644 index 000000000000..b6f1f1cf218e --- /dev/null +++ b/test/Driver/hip-device-compile.hip @@ -0,0 +1,72 @@ +// REQUIRES: clang-driver +// REQUIRES: x86-registered-target +// REQUIRES: amdgpu-registered-target + +// If -emit-llvm and/or -S is used in device only compilation, +// the output should not be bundled. + +// RUN: %clang -c -emit-llvm --cuda-device-only -### -target x86_64-linux-gnu \ +// RUN: -o a.bc -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib=lib1.bc \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: 2>&1 | FileCheck -check-prefixes=CHECK,BC %s + +// RUN: %clang -c -S -emit-llvm --cuda-device-only -### -target x86_64-linux-gnu \ +// RUN: -o a.ll -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib=lib1.bc \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: 2>&1 | FileCheck -check-prefixes=CHECK,LL %s + +// RUN: %clang -c -S --cuda-device-only -### -target x86_64-linux-gnu \ +// RUN: -o a.s -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib=lib1.bc \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: 2>&1 | FileCheck -check-prefixes=CHECK,ASM %s + +// CHECK: {{".*clang.*"}} "-cc1" "-triple" "amdgcn-amd-amdhsa" +// CHECK-SAME: "-aux-triple" "x86_64-unknown-linux-gnu" +// BC-SAME: "-emit-llvm-bc" +// LL-SAME: "-emit-llvm" +// ASM-NOT: "-emit-llvm" +// CHECK-SAME: "-main-file-name" "a.cu" {{.*}} "-target-cpu" "gfx900" +// CHECK-SAME: "-fcuda-is-device" +// CHECK-SAME: {{".*lib1.bc"}} +// BC-SAME: "-o" "a.bc" +// LL-SAME: "-o" "a.ll" +// ASM-SAME: "-o" "a.s" +// CHECK-SAME: {{".*a.cu"}} + +// CHECK-NOT: {{"*.llvm-link"}} +// CHECK-NOT: {{".*opt"}} +// CHECK-NOT: {{".*llc"}} +// CHECK-NOT: {{".*lld"}} +// CHECK-NOT: {{".*clang-offload-bundler"}} +// CHECK-NOT: {{".*ld.*"}} + +// If neither -emit-llvm nor -S is used in device only compilation, +// the output should be bundled. + +// RUN: %clang -c --cuda-device-only -### -target x86_64-linux-gnu \ +// RUN: -o a.s -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib=lib1.bc \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: 2>&1 | FileCheck -check-prefixes=BUNDLE %s + +// RUN: %clang --cuda-device-only -### -target x86_64-linux-gnu \ +// RUN: -o a.s -x hip --cuda-gpu-arch=gfx900 \ +// RUN: --hip-device-lib=lib1.bc \ +// RUN: --hip-device-lib-path=%S/Inputs/hip_multiple_inputs/lib1 \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: 2>&1 | FileCheck -check-prefixes=BUNDLE %s + +// BUNDLE: {{"*.clang.*"}} +// BUNDLE: {{"*.llvm-link"}} +// BUNDLE: {{".*opt"}} +// BUNDLE: {{".*llc"}} +// BUNDLE: {{".*lld"}} +// BUNDLE: {{".*clang-offload-bundler"}} + diff --git a/test/Driver/print-libgcc-file-name-clangrt.c b/test/Driver/print-libgcc-file-name-clangrt.c index ce941dc4a128..74a88e565bb8 100644 --- a/test/Driver/print-libgcc-file-name-clangrt.c +++ b/test/Driver/print-libgcc-file-name-clangrt.c @@ -2,11 +2,13 @@ // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=x86_64-pc-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-X8664 %s // CHECK-CLANGRT-X8664: libclang_rt.builtins-x86_64.a // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=i386-pc-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s // CHECK-CLANGRT-I386: libclang_rt.builtins-i386.a @@ -14,24 +16,29 @@ // // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=i686-pc-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-I386 %s // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=arm-linux-gnueabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-ARM %s // CHECK-CLANGRT-ARM: libclang_rt.builtins-arm.a // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=arm-linux-androideabi \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ANDROID %s // CHECK-CLANGRT-ARM-ANDROID: libclang_rt.builtins-arm-android.a // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=arm-linux-gnueabihf \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-ARMHF %s // CHECK-CLANGRT-ARMHF: libclang_rt.builtins-armhf.a // RUN: %clang -rtlib=compiler-rt -print-libgcc-file-name 2>&1 \ // RUN: --target=arm-linux-gnueabi -mfloat-abi=hard \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ // RUN: | FileCheck --check-prefix=CHECK-CLANGRT-ARM-ABI %s // CHECK-CLANGRT-ARM-ABI: libclang_rt.builtins-armhf.a diff --git a/test/Lexer/cxx-features.cpp b/test/Lexer/cxx-features.cpp index cda6f888cbce..868ec24a1d9f 100644 --- a/test/Lexer/cxx-features.cpp +++ b/test/Lexer/cxx-features.cpp @@ -34,6 +34,10 @@ #error "wrong value for __cpp_char8_t" #endif +#if check(constexpr_dynamic_alloc, 0, 0, 0, 0, 201907) +#error "wrong value for __cpp_constexpr_dynamic_alloc" +#endif + #if check(constinit, 0, 0, 0, 0, 201907) #error "wrong value for __cpp_constinit" #endif diff --git a/test/OpenMP/declare_target_codegen.cpp b/test/OpenMP/declare_target_codegen.cpp index dd4ab3c8248e..f1074ee5b294 100644 --- a/test/OpenMP/declare_target_codegen.cpp +++ b/test/OpenMP/declare_target_codegen.cpp @@ -1,29 +1,22 @@ // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -o - | FileCheck %s // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix HOST5 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50 -DOMP5 -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix DEV5 +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix DEV5 // RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix KMPC-ONLY -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50 -DOMP5 -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix KMPC-ONLY - -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix KMPC-ONLY -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix KMPC-ONLY // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix SIMD-ONLY // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -fopenmp-version=50 -DOMP5 -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix SIMD-ONLY +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -fopenmp-version=50 -DOMP5 | FileCheck %s --check-prefix SIMD-ONLY // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t -// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o -| FileCheck %s --check-prefix SIMD-ONLY +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -emit-pch -o %t +// RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -include-pch %t -verify -o - | FileCheck %s --check-prefix SIMD-ONLY // expected-no-diagnostics diff --git a/test/OpenMP/declare_variant_ast_print.c b/test/OpenMP/declare_variant_ast_print.c index 4c91e2e54184..ad1ef91eca14 100644 --- a/test/OpenMP/declare_variant_ast_print.c +++ b/test/OpenMP/declare_variant_ast_print.c @@ -10,9 +10,11 @@ int foo(void); #pragma omp declare variant(foo) match(xxx={vvv}) #pragma omp declare variant(foo) match(implementation={vendor(ibm)}, implementation={vendor(llvm)}) #pragma omp declare variant(foo) match(implementation={vendor(unknown)}) +#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)}) int bar(void); // CHECK: int foo(); +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):ibm)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)}) diff --git a/test/OpenMP/declare_variant_ast_print.cpp b/test/OpenMP/declare_variant_ast_print.cpp index 1760751c8034..77f03f518552 100644 --- a/test/OpenMP/declare_variant_ast_print.cpp +++ b/test/OpenMP/declare_variant_ast_print.cpp @@ -17,7 +17,8 @@ T foofoo() { return T(); } // CHECK-NEXT: return int(); // CHECK-NEXT: } -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(5):ibm)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}) // CHECK-NEXT: int bar(); @@ -25,12 +26,14 @@ T foofoo() { return T(); } #pragma omp declare variant(foofoo ) match(xxx = {vvv}) #pragma omp declare variant(foofoo ) match(implementation={vendor(ibm)}, implementation={vendor(llvm)}) #pragma omp declare variant(foofoo ) match(implementation={vendor(unknown)}) +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm)}) int bar(); -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(C + 5):ibm)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}) -// CHECK-NEXT: template T barbar(); +// CHECK-NEXT: template T barbar(); #pragma omp declare variant(foofoo ) match(xxx = {}) #pragma omp declare variant(foofoo ) match(xxx = {vvv}) #pragma omp declare variant(foofoo ) match(user = {score() : condition()}) @@ -39,19 +42,21 @@ int bar(); #pragma omp declare variant(foofoo ) match(user = {condition()}) #pragma omp declare variant(foofoo ) match(implementation={vendor(ibm)}, implementation={vendor(llvm)}) #pragma omp declare variant(foofoo ) match(implementation={vendor(unknown)}) -template +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm)}) +template T barbar(); -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(3 + 5):ibm)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}) -// CHECK-NEXT: template<> int barbar(); +// CHECK-NEXT: template<> int barbar(); // CHECK-NEXT: int baz() { -// CHECK-NEXT: return barbar(); +// CHECK-NEXT: return barbar(); // CHECK-NEXT: } int baz() { - return barbar(); + return barbar(); } // CHECK: template void h_ref(C *hp, C *hp2, C *hq, C *lin) { diff --git a/test/OpenMP/declare_variant_messages.c b/test/OpenMP/declare_variant_messages.c index 0eeaae052302..7e69cec1f1b0 100644 --- a/test/OpenMP/declare_variant_messages.c +++ b/test/OpenMP/declare_variant_messages.c @@ -30,6 +30,11 @@ int foo(void); #pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foo) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} +#pragma omp declare variant(foo) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} +#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integer constant expression}} +#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)}) int bar(void); // expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} diff --git a/test/OpenMP/declare_variant_messages.cpp b/test/OpenMP/declare_variant_messages.cpp index ca61c53b0f6c..88e724d12470 100644 --- a/test/OpenMP/declare_variant_messages.cpp +++ b/test/OpenMP/declare_variant_messages.cpp @@ -8,7 +8,7 @@ int foo(); template -T foofoo(); +T foofoo(); // expected-note 2 {{declared here}} #pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} #pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} @@ -33,6 +33,11 @@ T foofoo(); #pragma omp declare variant(foofoo ) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foofoo ) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foofoo ) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo' cannot be used in a constant expression}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm)}) int bar(); #pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} @@ -57,7 +62,12 @@ int bar(); #pragma omp declare variant(foofoo ) match(user = {condition()}) #pragma omp declare variant(foofoo ) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} #pragma omp declare variant(foofoo ) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}} -template +#pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo' cannot be used in a constant expression}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm)}) +template T barbar(); // expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} diff --git a/test/OpenMP/target_messages.cpp b/test/OpenMP/target_messages.cpp index 9bd8b3749e05..5f22fbcaf606 100644 --- a/test/OpenMP/target_messages.cpp +++ b/test/OpenMP/target_messages.cpp @@ -13,14 +13,12 @@ // NO-HOST-BC: The provided host compiler IR file '1111.bc' is required to generate code for OpenMP target regions but cannot be found. // RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm-bc %s -o %t-ppc-host.bc -DREGION_HOST -// RUN: not %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -DREGION_DEVICE 2>&1 | FileCheck %s --check-prefix NO-REGION -// NO-REGION: Offloading entry for target region is incorrect: either the address or the ID is invalid. -// NO-REGION-NOT: Offloading entry for target region is incorrect: either the address or the ID is invalid. +// RUN: not %clang_cc1 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=powerpc64le-ibm-linux-gnu -emit-llvm %s -fopenmp-is-device -fopenmp-host-ir-file-path %t-ppc-host.bc -o - -DREGION_DEVICE 2>&1 #if defined(REGION_HOST) || defined(REGION_DEVICE) void foo() { #ifdef REGION_HOST -#pragma omp target +#pragma omp target // expected-error {{Offloading entry for target region in _Z3foov is incorrect: either the address or the ID is invalid.}} ; #endif #ifdef REGION_DEVICE diff --git a/test/Sema/warn-bitwise-negation-bool.c b/test/Sema/warn-bitwise-negation-bool.c new file mode 100644 index 000000000000..1d39f0c576f8 --- /dev/null +++ b/test/Sema/warn-bitwise-negation-bool.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wbool-operation %s +// RUN: %clang_cc1 -x c -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wbool-operation %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -verify %s +// RUN: %clang_cc1 -x c++ -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +#ifdef __cplusplus +typedef bool boolean; +#else +typedef _Bool boolean; +#endif + +void test(boolean b, int i) { + b = ~b; // expected-warning {{bitwise negation of a boolean expression always evaluates to 'true'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:8}:"!" + b = ~(b); // expected-warning {{bitwise negation of a boolean expression always evaluates to 'true'}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:8}:"!" + b = ~i; +} diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index bd7094f4d4f2..27ad0f654f56 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -1108,6 +1108,11 @@ namespace MemberPointer { static_assert((int Derived::*)(int Mid<0>::*)&Mid<0>::n != (int Derived::*)(int Mid<1>::*)&Mid<1>::n, ""); static_assert(&Mid<0>::n == (int Mid<0>::*)&Base::n, ""); + + constexpr int apply(const A &a, int (A::*f)() const) { + return (a.*f)(); + } + static_assert(apply(A(2), &A::f) == 5, ""); } namespace ArrayBaseDerived { diff --git a/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp new file mode 100644 index 000000000000..23582f2e3026 --- /dev/null +++ b/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp @@ -0,0 +1,168 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s -DNEW=__builtin_operator_new -DDELETE=__builtin_operator_delete +// RUN: %clang_cc1 -std=c++2a -verify %s "-DNEW=operator new" "-DDELETE=operator delete" +// RUN: %clang_cc1 -std=c++2a -verify %s "-DNEW=::operator new" "-DDELETE=::operator delete" + +constexpr bool alloc_from_user_code() { + void *p = NEW(sizeof(int)); // expected-note {{cannot allocate untyped memory in a constant expression; use 'std::allocator::allocate'}} + DELETE(p); + return true; +} +static_assert(alloc_from_user_code()); // expected-error {{constant expression}} expected-note {{in call}} + +namespace std { + using size_t = decltype(sizeof(0)); + // FIXME: It would be preferable to point these notes at the location of the call to allocator<...>::[de]allocate instead + template struct allocator { + constexpr T *allocate(size_t N) { + return (T*)NEW(sizeof(T) * N); // expected-note 3{{heap allocation}} expected-note {{not deallocated}} + } + constexpr void deallocate(void *p) { + DELETE(p); // expected-note 2{{'std::allocator<...>::deallocate' used to delete pointer to object allocated with 'new'}} + } + }; +} + +constexpr bool alloc_via_std_allocator() { + std::allocator alloc; + int *p = alloc.allocate(1); + alloc.deallocate(p); + return true; +} +static_assert(alloc_via_std_allocator()); + +template<> struct std::allocator { + constexpr void *allocate() { return NEW(8); } // expected-note {{cannot allocate memory of function type 'void ()'}} +}; +constexpr void *fn = std::allocator().allocate(); // expected-error {{constant expression}} expected-note {{in call}} + +struct Incomplete; +template<> struct std::allocator { + constexpr void *allocate() { return NEW(8); } // expected-note {{cannot allocate memory of incomplete type 'Incomplete'}} +}; +constexpr void *incomplete = std::allocator().allocate(); // expected-error {{constant expression}} expected-note {{in call}} + +struct WrongSize { char x[5]; }; +static_assert(sizeof(WrongSize) == 5); +template<> struct std::allocator { + constexpr void *allocate() { return NEW(7); } // expected-note {{allocated size 7 is not a multiple of size 5 of element type 'WrongSize'}} +}; +constexpr void *wrong_size = std::allocator().allocate(); // expected-error {{constant expression}} expected-note {{in call}} + +constexpr bool mismatched(int alloc_kind, int dealloc_kind) { + int *p; + switch (alloc_kind) { + case 0: + p = new int; // expected-note {{heap allocation}} + break; + case 1: + p = new int[1]; // expected-note {{heap allocation}} + break; + case 2: + p = std::allocator().allocate(1); + break; + } + switch (dealloc_kind) { + case 0: + delete p; // expected-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}} + break; + case 1: + delete[] p; // expected-note {{'delete' used to delete pointer to object allocated with 'std::allocator<...>::allocate'}} + break; + case 2: + std::allocator().deallocate(p); // expected-note 2{{in call}} + break; + } + return true; +} +static_assert(mismatched(0, 2)); // expected-error {{constant expression}} expected-note {{in call}} +static_assert(mismatched(1, 2)); // expected-error {{constant expression}} expected-note {{in call}} +static_assert(mismatched(2, 0)); // expected-error {{constant expression}} expected-note {{in call}} +static_assert(mismatched(2, 1)); // expected-error {{constant expression}} expected-note {{in call}} +static_assert(mismatched(2, 2)); + +constexpr int *escape = std::allocator().allocate(3); // expected-error {{constant expression}} expected-note {{pointer to subobject of heap-allocated}} +constexpr int leak = (std::allocator().allocate(3), 0); // expected-error {{constant expression}} +constexpr int no_lifetime_start = (*std::allocator().allocate(1) = 1); // expected-error {{constant expression}} expected-note {{assignment to object outside its lifetime}} + +void *operator new(std::size_t, void *p) { return p; } +constexpr bool no_placement_new_in_user_code() { // expected-error {{never produces a constant expression}} + int a; + new (&a) int(42); // expected-note {{call to placement 'operator new'}} + return a == 42; +} + +namespace std { + constexpr bool placement_new_in_stdlib() { + int a; + new (&a) int(42); + return a == 42; + } +} +static_assert(std::placement_new_in_stdlib()); + +namespace std { + template + constexpr void construct_at(void *p, Args &&...args) { + new (p) T((Args&&)args...); // #new + } +} + +constexpr bool call_std_construct_at() { + int *p = std::allocator().allocate(3); + std::construct_at(p, 1); + std::construct_at(p + 1, 2); + std::construct_at(p + 2, 3); + bool good = p[0] + p[1] + p[2] == 6; + std::allocator().deallocate(p); + return good; +} +static_assert(call_std_construct_at()); + +constexpr bool bad_construct_at_type() { + int a; + // expected-note@#new {{placement new would change type of storage from 'int' to 'float'}} + std::construct_at(&a, 1.0f); // expected-note {{in call}} + return true; +} +static_assert(bad_construct_at_type()); // expected-error{{}} expected-note {{in call}} + +constexpr bool bad_construct_at_subobject() { + struct X { int a, b; }; + union A { + int a; + X x; + }; + A a = {1}; + // expected-note@#new {{construction of subobject of member 'x' of union with active member 'a' is not allowed in a constant expression}} + std::construct_at(&a.x.a, 1); // expected-note {{in call}} + return true; +} +static_assert(bad_construct_at_subobject()); // expected-error{{}} expected-note {{in call}} + +constexpr bool change_union_member() { + union U { + int a; + int b; + }; + U u = {.a = 1}; + std::construct_at(&u.b, 2); + return u.b == 2; +} +static_assert(change_union_member()); + +int external; +// expected-note@#new {{visible outside}} +static_assert((std::construct_at(&external, 1), true)); // expected-error{{}} expected-note {{in call}} + +constexpr int &&temporary = 0; // expected-note {{created here}} +// expected-note@#new {{construction of temporary is not allowed in a constant expression outside the expression that created the temporary}} +static_assert((std::construct_at(&temporary, 1), true)); // expected-error{{}} expected-note {{in call}} + +constexpr bool construct_after_lifetime() { + int *p = new int; + delete p; + // expected-note@#new {{construction of heap allocated object that has been deleted}} + std::construct_at(p); // expected-note {{in call}} + return true; +} +static_assert(construct_after_lifetime()); // expected-error {{}} expected-note {{in call}} diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp index 055f37bb05fe..6b4eb12755fd 100644 --- a/test/SemaTemplate/instantiate-expr-4.cpp +++ b/test/SemaTemplate/instantiate-expr-4.cpp @@ -192,6 +192,13 @@ struct TypeId0 { } }; +template +struct TypeId1 { + const std::type_info &f() { + return typeid(T); // expected-error-re 2{{type operand 'void () {{const|&}}' of 'typeid' cannot have '{{const|&}}' qualifier}} + } +}; + struct Abstract { virtual void f() = 0; }; @@ -199,6 +206,8 @@ struct Abstract { template struct TypeId0; template struct TypeId0; // expected-note{{instantiation of member function}} template struct TypeId0; +template struct TypeId1; // expected-note{{instantiation of}} +template struct TypeId1; // expected-warning 0-1{{C++11}} expected-note{{instantiation of}} // --------------------------------------------------------------------- // type traits diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp index bdf766331252..3249d0dc1941 100644 --- a/test/SemaTemplate/temp_arg_nontype.cpp +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -482,3 +482,15 @@ namespace dependent_backreference { template void a() { X x; } template void b() { X x; } // expected-note {{substituting}} } + +namespace instantiation_dependent { + template void f(int); + template int &f(...); + int &rf = f(0); + + // FIXME: This fails because we mishandle instantiation-dependent array bounds :( + int arr[sizeof(sizeof(int))]; + template void g(int); + template int &g(...); + int &rg = g(0); // expected-error {{cannot bind}} +} diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index d7759bc6df3b..e982c8b2ab07 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -644,7 +644,8 @@ TEST_F(FormatTest, FormatShortBracedStatements) { AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse; AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine = true; - AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement = true; + AllowSimpleBracedStatements.BraceWrapping.AfterControlStatement = + FormatStyle::BWACS_Always; verifyFormat("if (true) {}", AllowSimpleBracedStatements); verifyFormat("if constexpr (true) {}", AllowSimpleBracedStatements); @@ -1168,7 +1169,7 @@ TEST_F(FormatTest, FormatsSwitchStatement) { Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Never; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterCaseLabel = true; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; EXPECT_EQ("switch (n)\n" "{\n" " case 0:\n" @@ -1370,7 +1371,7 @@ TEST_F(FormatTest, ShortCaseLabels) { Style.AllowShortCaseLabelsOnASingleLine = true; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterCaseLabel = true; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; EXPECT_EQ("switch (n)\n" "{\n" " case 0:\n" @@ -1441,6 +1442,131 @@ TEST_F(FormatTest, FormatsLabels) { "}"); } +TEST_F(FormatTest, MultiLineControlStatements) { + FormatStyle Style = getLLVMStyle(); + Style.BreakBeforeBraces = FormatStyle::BraceBreakingStyle::BS_Custom; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_MultiLine; + Style.ColumnLimit = 20; + // Short lines should keep opening brace on same line. + EXPECT_EQ("if (foo) {\n" + " bar();\n" + "}", + format("if(foo){bar();}", Style)); + EXPECT_EQ("if (foo) {\n" + " bar();\n" + "} else {\n" + " baz();\n" + "}", + format("if(foo){bar();}else{baz();}", Style)); + EXPECT_EQ("if (foo && bar) {\n" + " baz();\n" + "}", + format("if(foo&&bar){baz();}", Style)); + EXPECT_EQ("if (foo) {\n" + " bar();\n" + "} else if (baz) {\n" + " quux();\n" + "}", + format("if(foo){bar();}else if(baz){quux();}", Style)); + EXPECT_EQ( + "if (foo) {\n" + " bar();\n" + "} else if (baz) {\n" + " quux();\n" + "} else {\n" + " foobar();\n" + "}", + format("if(foo){bar();}else if(baz){quux();}else{foobar();}", Style)); + EXPECT_EQ("for (;;) {\n" + " foo();\n" + "}", + format("for(;;){foo();}")); + EXPECT_EQ("while (1) {\n" + " foo();\n" + "}", + format("while(1){foo();}", Style)); + EXPECT_EQ("switch (foo) {\n" + "case bar:\n" + " return;\n" + "}", + format("switch(foo){case bar:return;}", Style)); + EXPECT_EQ("try {\n" + " foo();\n" + "} catch (...) {\n" + " bar();\n" + "}", + format("try{foo();}catch(...){bar();}", Style)); + EXPECT_EQ("do {\n" + " foo();\n" + "} while (bar &&\n" + " baz);", + format("do{foo();}while(bar&&baz);", Style)); + // Long lines should put opening brace on new line. + EXPECT_EQ("if (foo && bar &&\n" + " baz)\n" + "{\n" + " quux();\n" + "}", + format("if(foo&&bar&&baz){quux();}", Style)); + EXPECT_EQ("if (foo && bar &&\n" + " baz)\n" + "{\n" + " quux();\n" + "}", + format("if (foo && bar &&\n" + " baz) {\n" + " quux();\n" + "}", + Style)); + EXPECT_EQ("if (foo) {\n" + " bar();\n" + "} else if (baz ||\n" + " quux)\n" + "{\n" + " foobar();\n" + "}", + format("if(foo){bar();}else if(baz||quux){foobar();}", Style)); + EXPECT_EQ( + "if (foo) {\n" + " bar();\n" + "} else if (baz ||\n" + " quux)\n" + "{\n" + " foobar();\n" + "} else {\n" + " barbaz();\n" + "}", + format("if(foo){bar();}else if(baz||quux){foobar();}else{barbaz();}", + Style)); + EXPECT_EQ("for (int i = 0;\n" + " i < 10; ++i)\n" + "{\n" + " foo();\n" + "}", + format("for(int i=0;i<10;++i){foo();}", Style)); + EXPECT_EQ("while (foo || bar ||\n" + " baz)\n" + "{\n" + " quux();\n" + "}", + format("while(foo||bar||baz){quux();}", Style)); + EXPECT_EQ("switch (\n" + " foo = barbaz)\n" + "{\n" + "case quux:\n" + " return;\n" + "}", + format("switch(foo=barbaz){case quux:return;}", Style)); + EXPECT_EQ("try {\n" + " foo();\n" + "} catch (\n" + " Exception &bar)\n" + "{\n" + " baz();\n" + "}", + format("try{foo();}catch(Exception&bar){baz();}", Style)); +} + //===----------------------------------------------------------------------===// // Tests for classes, namespaces, etc. //===----------------------------------------------------------------------===// @@ -2940,7 +3066,7 @@ TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) { "};")); FormatStyle Style = getLLVMStyle(); Style.BreakBeforeBraces = FormatStyle::BS_Custom; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; Style.BraceWrapping.AfterFunction = true; EXPECT_EQ("void f()\n" "try\n" @@ -12261,7 +12387,6 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterCaseLabel); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterClass); - CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterControlStatement); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterEnum); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterFunction); CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterNamespace); @@ -12469,6 +12594,25 @@ TEST_F(FormatTest, ParsesConfiguration) { CHECK_PARSE("BreakBeforeBraces: Custom", BreakBeforeBraces, FormatStyle::BS_Custom); + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Never; + CHECK_PARSE("BraceWrapping:\n" + " AfterControlStatement: MultiLine", + BraceWrapping.AfterControlStatement, + FormatStyle::BWACS_MultiLine); + CHECK_PARSE("BraceWrapping:\n" + " AfterControlStatement: Always", + BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Always); + CHECK_PARSE("BraceWrapping:\n" + " AfterControlStatement: Never", + BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never); + // For backward compatibility: + CHECK_PARSE("BraceWrapping:\n" + " AfterControlStatement: true", + BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Always); + CHECK_PARSE("BraceWrapping:\n" + " AfterControlStatement: false", + BraceWrapping.AfterControlStatement, FormatStyle::BWACS_Never); + Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_All; CHECK_PARSE("AlwaysBreakAfterReturnType: None", AlwaysBreakAfterReturnType, FormatStyle::RTBS_None); diff --git a/unittests/Format/FormatTestObjC.cpp b/unittests/Format/FormatTestObjC.cpp index 8fb93195881d..063eb5f58f1f 100644 --- a/unittests/Format/FormatTestObjC.cpp +++ b/unittests/Format/FormatTestObjC.cpp @@ -207,7 +207,7 @@ TEST_F(FormatTestObjC, FormatObjCAutoreleasepool) { " f();\n" "}\n"); Style.BreakBeforeBraces = FormatStyle::BS_Custom; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; verifyFormat("@autoreleasepool\n" "{\n" " f();\n" @@ -237,7 +237,7 @@ TEST_F(FormatTestObjC, FormatObjCSynchronized) { " f();\n" "}\n"); Style.BreakBeforeBraces = FormatStyle::BS_Custom; - Style.BraceWrapping.AfterControlStatement = true; + Style.BraceWrapping.AfterControlStatement = FormatStyle::BWACS_Always; verifyFormat("@synchronized(self)\n" "{\n" " f();\n" diff --git a/unittests/Tooling/StencilTest.cpp b/unittests/Tooling/StencilTest.cpp index 2202693f023d..f441fae80322 100644 --- a/unittests/Tooling/StencilTest.cpp +++ b/unittests/Tooling/StencilTest.cpp @@ -20,14 +20,19 @@ using namespace tooling; using namespace ast_matchers; namespace { +using ::llvm::Failed; using ::llvm::HasValue; +using ::llvm::StringError; using ::testing::AllOf; using ::testing::Eq; using ::testing::HasSubstr; using MatchResult = MatchFinder::MatchResult; using stencil::access; +using stencil::addressOf; using stencil::cat; +using stencil::deref; using stencil::dPrint; +using stencil::expression; using stencil::ifBound; using stencil::run; using stencil::text; @@ -104,7 +109,7 @@ class StencilTest : public ::testing::Test { ADD_FAILURE() << "Expected failure but succeeded: " << *ResultOrErr; } else { auto Err = llvm::handleErrors(ResultOrErr.takeError(), - [&Matcher](const llvm::StringError &Err) { + [&Matcher](const StringError &Err) { EXPECT_THAT(Err.getMessage(), Matcher); }); if (Err) { @@ -183,6 +188,15 @@ void testExpr(StringRef Id, StringRef Snippet, const Stencil &Stencil, EXPECT_THAT_EXPECTED(Stencil.eval(StmtMatch->Result), HasValue(Expected)); } +void testFailure(StringRef Id, StringRef Snippet, const Stencil &Stencil, + testing::Matcher MessageMatcher) { + auto StmtMatch = matchStmt(Snippet, expr().bind(Id)); + ASSERT_TRUE(StmtMatch); + EXPECT_THAT_EXPECTED(Stencil.eval(StmtMatch->Result), + Failed(testing::Property( + &StringError::getMessage, MessageMatcher))); +} + TEST_F(StencilTest, SelectionOp) { StringRef Id = "id"; testExpr(Id, "3;", cat(node(Id)), "3"); @@ -198,6 +212,56 @@ TEST_F(StencilTest, IfBoundOpUnbound) { testExpr(Id, "3;", cat(ifBound("other", text("5"), text("7"))), "7"); } +TEST_F(StencilTest, ExpressionOpNoParens) { + StringRef Id = "id"; + testExpr(Id, "3;", cat(expression(Id)), "3"); +} + +// Don't parenthesize a parens expression. +TEST_F(StencilTest, ExpressionOpNoParensParens) { + StringRef Id = "id"; + testExpr(Id, "(3);", cat(expression(Id)), "(3)"); +} + +TEST_F(StencilTest, ExpressionOpBinaryOpParens) { + StringRef Id = "id"; + testExpr(Id, "3+4;", cat(expression(Id)), "(3+4)"); +} + +// `expression` shares code with other ops, so we get sufficient coverage of the +// error handling code with this test. If that changes in the future, more error +// tests should be added. +TEST_F(StencilTest, ExpressionOpUnbound) { + StringRef Id = "id"; + testFailure(Id, "3;", cat(expression("ACACA")), + AllOf(HasSubstr("ACACA"), HasSubstr("not bound"))); +} + +TEST_F(StencilTest, DerefPointer) { + StringRef Id = "id"; + testExpr(Id, "int *x; x;", cat(deref(Id)), "*x"); +} + +TEST_F(StencilTest, DerefBinOp) { + StringRef Id = "id"; + testExpr(Id, "int *x; x + 1;", cat(deref(Id)), "*(x + 1)"); +} + +TEST_F(StencilTest, DerefAddressExpr) { + StringRef Id = "id"; + testExpr(Id, "int x; &x;", cat(deref(Id)), "x"); +} + +TEST_F(StencilTest, AddressOfValue) { + StringRef Id = "id"; + testExpr(Id, "int x; x;", cat(addressOf(Id)), "&x"); +} + +TEST_F(StencilTest, AddressOfDerefExpr) { + StringRef Id = "id"; + testExpr(Id, "int *x; *x;", cat(addressOf(Id)), "x"); +} + TEST_F(StencilTest, AccessOpValue) { StringRef Snippet = R"cc( S x; diff --git a/www/cxx_status.html b/www/cxx_status.html index cebe2ed136d3..041d6aa242c7 100755 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -1003,14 +1003,13 @@

C++2a implementation status

P1331R2 - SVN + SVN P1668R1 P0784R7 - Partial Prohibit aggregates with user-declared constructors