diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f2b27893b7a9d..acd9dd9298ce1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -886,6 +886,9 @@ Bug Fixes to C++ Support out of a module (which is the case e.g. in MSVC's implementation of ``std`` module). (#GH118218) - Fixed a pack expansion issue in checking unexpanded parameter sizes. (#GH17042) - Fixed a bug where captured structured bindings were modifiable inside non-mutable lambda (#GH95081) +- Passing incomplete types to ``__is_base_of`` and other builtin type traits for which the corresponding + standard type trait mandates a complete type is now a hard (non-sfinae-friendly) error + (`LWG3929 `__.) (#GH121278) - Clang now identifies unexpanded parameter packs within the type constraint on a non-type template parameter. (#GH88866) - Fixed an issue while resolving type of expression indexing into a pack of values of non-dependent type (#GH121242) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index b5b47ae274601..468c16050e2bf 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3568,6 +3568,19 @@ def Frexp : FPMathTemplate, LibBuiltin<"math.h"> { let AddBuiltinPrefixedAlias = 1; } +def Sincos : FPMathTemplate, GNULibBuiltin<"math.h"> { + let Spellings = ["sincos"]; + let Attributes = [NoThrow]; + let Prototype = "void(T, T*, T*)"; + let AddBuiltinPrefixedAlias = 1; +} + +def SincosF16F128 : F16F128MathTemplate, Builtin { + let Spellings = ["__builtin_sincos"]; + let Attributes = [FunctionWithBuiltinPrefix, NoThrow]; + let Prototype = "void(T, T*, T*)"; +} + def Ldexp : FPMathTemplate, LibBuiltin<"math.h"> { let Spellings = ["ldexp"]; let Attributes = [NoThrow, ConstIgnoringErrnoAndExceptions]; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 1ed379c76c8ea..f3593f5313340 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -291,6 +291,8 @@ def warn_function_always_inline_attribute_mismatch : Warning< "inlining may change runtime behaviour">, InGroup; def err_function_always_inline_new_za : Error< "always_inline function %0 has new za state">; +def err_function_always_inline_new_zt0 + : Error<"always_inline function %0 has new zt0 state">; def warn_avx_calling_convention : Warning<"AVX vector %select{return|argument}0 of type %1 without '%2' " diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 330ae045616ab..03fb7ca9bc3c3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9361,7 +9361,7 @@ def note_inequality_comparison_to_or_assign : Note< "use '|=' to turn this inequality comparison into an or-assignment">; def err_incomplete_type_used_in_type_trait_expr : Error< - "incomplete type %0 used in type trait expression">; + "incomplete type %0 used in type trait expression">, NoSFINAE; // C++20 constinit and require_constant_initialization attribute def warn_cxx20_compat_constinit : Warning< diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 12edfbb171d34..640cf1412dd98 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3508,8 +3508,6 @@ def fno_verbose_asm : Flag<["-"], "fno-verbose-asm">, Group, Visibility<[ClangOption, CC1Option]>, MarshallingInfoNegativeFlag>; def fno_working_directory : Flag<["-"], "fno-working-directory">, Group; -def fno_wrapv : Flag<["-"], "fno-wrapv">, Group, - Visibility<[ClangOption, FlangOption]>; def fobjc_arc : Flag<["-"], "fobjc-arc">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Synthesize retain and release calls for Objective-C pointers">; @@ -4280,8 +4278,10 @@ defm virtual_function_elimination : BoolFOption<"virtual-function-elimination", NegFlag, BothFlags<[], [ClangOption, CLOption]>>; def fwrapv : Flag<["-"], "fwrapv">, Group, - Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, + Visibility<[ClangOption, CLOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; +def fno_wrapv : Flag<["-"], "fno-wrapv">, Group, + Visibility<[ClangOption, CLOption, FlangOption]>; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Store string literals as writable data">, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 862a30c0e7363..aca14cf813c4b 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -25,6 +25,8 @@ namespace ento { class MemRegion; +using SymbolID = unsigned; + /// Symbolic value. These values used to capture symbolic execution of /// the program. class SymExpr : public llvm::FoldingSetNode { @@ -39,9 +41,19 @@ class SymExpr : public llvm::FoldingSetNode { private: Kind K; + /// A unique identifier for this symbol. + /// + /// It is useful for SymbolData to easily differentiate multiple symbols, but + /// also for "ephemeral" symbols, such as binary operations, because this id + /// can be used for arranging constraints or equivalence classes instead of + /// unstable pointer values. + /// + /// Note, however, that it can't be used in Profile because SymbolManager + /// needs to compute Profile before allocating SymExpr. + const SymbolID Sym; protected: - SymExpr(Kind k) : K(k) {} + SymExpr(Kind k, SymbolID Sym) : K(k), Sym(Sym) {} static bool isValidTypeForSymbol(QualType T) { // FIXME: Depending on whether we choose to deprecate structural symbols, @@ -56,6 +68,14 @@ class SymExpr : public llvm::FoldingSetNode { Kind getKind() const { return K; } + /// Get a unique identifier for this symbol. + /// The ID is unique across all SymExprs in a SymbolManager. + /// They reflect the allocation order of these SymExprs, + /// and are likely stable across runs. + /// Used as a key in SymbolRef containers and as part of identity + /// for SymbolData, e.g. SymbolConjured with ID = 7 is "conj_$7". + SymbolID getSymbolID() const { return Sym; } + virtual void dump() const; virtual void dumpToStream(raw_ostream &os) const {} @@ -112,19 +132,14 @@ inline raw_ostream &operator<<(raw_ostream &os, using SymbolRef = const SymExpr *; using SymbolRefSmallVectorTy = SmallVector; -using SymbolID = unsigned; /// A symbol representing data which can be stored in a memory location /// (region). class SymbolData : public SymExpr { - const SymbolID Sym; - void anchor() override; protected: - SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) { - assert(classof(this)); - } + SymbolData(Kind k, SymbolID sym) : SymExpr(k, sym) { assert(classof(this)); } public: ~SymbolData() override = default; @@ -132,8 +147,6 @@ class SymbolData : public SymExpr { /// Get a string representation of the kind of the region. virtual StringRef getKindStr() const = 0; - SymbolID getSymbolID() const { return Sym; } - unsigned computeComplexity() const override { return 1; }; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 73732d532f630..c530dff495238 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -25,6 +25,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableSet.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" #include @@ -43,15 +44,16 @@ class StoreManager; class SymbolRegionValue : public SymbolData { const TypedValueRegion *R; -public: + friend class SymExprAllocator; SymbolRegionValue(SymbolID sym, const TypedValueRegion *r) : SymbolData(SymbolRegionValueKind, sym), R(r) { assert(r); assert(isValidTypeForSymbol(r->getValueType())); } +public: LLVM_ATTRIBUTE_RETURNS_NONNULL - const TypedValueRegion* getRegion() const { return R; } + const TypedValueRegion *getRegion() const { return R; } static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) { profile.AddInteger((unsigned) SymbolRegionValueKind); @@ -84,7 +86,7 @@ class SymbolConjured : public SymbolData { const LocationContext *LCtx; const void *SymbolTag; -public: + friend class SymExprAllocator; SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx, QualType t, unsigned count, const void *symbolTag) : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count), @@ -98,6 +100,7 @@ class SymbolConjured : public SymbolData { assert(isValidTypeForSymbol(t)); } +public: /// It might return null. const Stmt *getStmt() const { return S; } unsigned getCount() const { return Count; } @@ -137,7 +140,7 @@ class SymbolDerived : public SymbolData { SymbolRef parentSymbol; const TypedValueRegion *R; -public: + friend class SymExprAllocator; SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r) : SymbolData(SymbolDerivedKind, sym), parentSymbol(parent), R(r) { assert(parent); @@ -145,6 +148,7 @@ class SymbolDerived : public SymbolData { assert(isValidTypeForSymbol(r->getValueType())); } +public: LLVM_ATTRIBUTE_RETURNS_NONNULL SymbolRef getParentSymbol() const { return parentSymbol; } LLVM_ATTRIBUTE_RETURNS_NONNULL @@ -180,12 +184,13 @@ class SymbolDerived : public SymbolData { class SymbolExtent : public SymbolData { const SubRegion *R; -public: + friend class SymExprAllocator; SymbolExtent(SymbolID sym, const SubRegion *r) : SymbolData(SymbolExtentKind, sym), R(r) { assert(r); } +public: LLVM_ATTRIBUTE_RETURNS_NONNULL const SubRegion *getRegion() const { return R; } @@ -222,7 +227,7 @@ class SymbolMetadata : public SymbolData { unsigned Count; const void *Tag; -public: + friend class SymExprAllocator; SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, const LocationContext *LCtx, unsigned count, const void *tag) : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), @@ -234,6 +239,7 @@ class SymbolMetadata : public SymbolData { assert(tag); } + public: LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion *getRegion() const { return R; } @@ -286,15 +292,16 @@ class SymbolCast : public SymExpr { /// The type of the result. QualType ToTy; -public: - SymbolCast(const SymExpr *In, QualType From, QualType To) - : SymExpr(SymbolCastKind), Operand(In), FromTy(From), ToTy(To) { + friend class SymExprAllocator; + SymbolCast(SymbolID Sym, const SymExpr *In, QualType From, QualType To) + : SymExpr(SymbolCastKind, Sym), Operand(In), FromTy(From), ToTy(To) { assert(In); assert(isValidTypeForSymbol(From)); // FIXME: GenericTaintChecker creates symbols of void type. // Otherwise, 'To' should also be a valid type. } +public: unsigned computeComplexity() const override { if (Complexity == 0) Complexity = 1 + Operand->computeComplexity(); @@ -332,9 +339,10 @@ class UnarySymExpr : public SymExpr { UnaryOperator::Opcode Op; QualType T; -public: - UnarySymExpr(const SymExpr *In, UnaryOperator::Opcode Op, QualType T) - : SymExpr(UnarySymExprKind), Operand(In), Op(Op), T(T) { + friend class SymExprAllocator; + UnarySymExpr(SymbolID Sym, const SymExpr *In, UnaryOperator::Opcode Op, + QualType T) + : SymExpr(UnarySymExprKind, Sym), Operand(In), Op(Op), T(T) { // Note, some unary operators are modeled as a binary operator. E.g. ++x is // modeled as x + 1. assert((Op == UO_Minus || Op == UO_Not) && "non-supported unary expression"); @@ -345,6 +353,7 @@ class UnarySymExpr : public SymExpr { assert(!Loc::isLocType(T) && "unary symbol should be nonloc"); } +public: unsigned computeComplexity() const override { if (Complexity == 0) Complexity = 1 + Operand->computeComplexity(); @@ -381,8 +390,8 @@ class BinarySymExpr : public SymExpr { QualType T; protected: - BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t) - : SymExpr(k), Op(op), T(t) { + BinarySymExpr(SymbolID Sym, Kind k, BinaryOperator::Opcode op, QualType t) + : SymExpr(k, Sym), Op(op), T(t) { assert(classof(this)); // Binary expressions are results of arithmetic. Pointer arithmetic is not // handled by binary expressions, but it is instead handled by applying @@ -425,14 +434,15 @@ class BinarySymExprImpl : public BinarySymExpr { LHSTYPE LHS; RHSTYPE RHS; -public: - BinarySymExprImpl(LHSTYPE lhs, BinaryOperator::Opcode op, RHSTYPE rhs, - QualType t) - : BinarySymExpr(ClassKind, op, t), LHS(lhs), RHS(rhs) { + friend class SymExprAllocator; + BinarySymExprImpl(SymbolID Sym, LHSTYPE lhs, BinaryOperator::Opcode op, + RHSTYPE rhs, QualType t) + : BinarySymExpr(Sym, ClassKind, op, t), LHS(lhs), RHS(rhs) { assert(getPointer(lhs)); assert(getPointer(rhs)); } +public: void dumpToStream(raw_ostream &os) const override { dumpToStreamImpl(os, LHS); dumpToStreamImpl(os, getOpcode()); @@ -478,6 +488,21 @@ using IntSymExpr = BinarySymExprImpl; +class SymExprAllocator { + SymbolID NextSymbolID = 0; + llvm::BumpPtrAllocator &Alloc; + +public: + explicit SymExprAllocator(llvm::BumpPtrAllocator &Alloc) : Alloc(Alloc) {} + + template SymT *make(ArgsT &&...Args) { + return new (Alloc) SymT(nextID(), std::forward(Args)...); + } + +private: + SymbolID nextID() { return NextSymbolID++; } +}; + class SymbolManager { using DataSetTy = llvm::FoldingSet; using SymbolDependTy = @@ -489,15 +514,14 @@ class SymbolManager { /// alive as long as the key is live. SymbolDependTy SymbolDependencies; - unsigned SymbolCounter = 0; - llvm::BumpPtrAllocator& BPAlloc; + SymExprAllocator Alloc; BasicValueFactory &BV; ASTContext &Ctx; public: SymbolManager(ASTContext &ctx, BasicValueFactory &bv, - llvm::BumpPtrAllocator& bpalloc) - : SymbolDependencies(16), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} + llvm::BumpPtrAllocator &bpalloc) + : SymbolDependencies(16), Alloc(bpalloc), BV(bv), Ctx(ctx) {} static bool canSymbolicate(QualType T); @@ -687,4 +711,36 @@ class SymbolVisitor { } // namespace clang +// Override the default definition that would use pointer values of SymbolRefs +// to order them, which is unstable due to ASLR. +// Use the SymbolID instead which reflect the order in which the symbols were +// allocated. This is usually stable across runs leading to the stability of +// ConstraintMap and other containers using SymbolRef as keys. +template <> +struct llvm::ImutContainerInfo + : public ImutProfileInfo { + using value_type = clang::ento::SymbolRef; + using value_type_ref = clang::ento::SymbolRef; + using key_type = value_type; + using key_type_ref = value_type_ref; + using data_type = bool; + using data_type_ref = bool; + + static key_type_ref KeyOfValue(value_type_ref D) { return D; } + static data_type_ref DataOfValue(value_type_ref) { return true; } + + static bool isEqual(clang::ento::SymbolRef LHS, clang::ento::SymbolRef RHS) { + return LHS->getSymbolID() == RHS->getSymbolID(); + } + + static bool isLess(clang::ento::SymbolRef LHS, clang::ento::SymbolRef RHS) { + return LHS->getSymbolID() < RHS->getSymbolID(); + } + + // This might seem redundant, but it is required because of the way + // ImmutableSet is implemented through AVLTree: + // same as ImmutableMap, but with a non-informative "data". + static bool isDataEqual(data_type_ref, data_type_ref) { return true; } +}; + #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8c8ccdb61dc01..ba66d36278567 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1618,9 +1618,9 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { std::pair CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { // If the callee is marked nodiscard, return that attribute - const Decl *D = getCalleeDecl(); - if (const auto *A = D->getAttr()) - return {nullptr, A}; + if (const Decl *D = getCalleeDecl()) + if (const auto *A = D->getAttr()) + return {nullptr, A}; // If the return type is a struct, union, or enum that is marked nodiscard, // then return the return type attribute. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 4d4b7428abd50..c419fb0cc055e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -835,6 +835,38 @@ static Value *emitFrexpBuiltin(CodeGenFunction &CGF, const CallExpr *E, return CGF.Builder.CreateExtractValue(Call, 0); } +static void emitSincosBuiltin(CodeGenFunction &CGF, const CallExpr *E, + llvm::Intrinsic::ID IntrinsicID) { + llvm::Value *Val = CGF.EmitScalarExpr(E->getArg(0)); + llvm::Value *Dest0 = CGF.EmitScalarExpr(E->getArg(1)); + llvm::Value *Dest1 = CGF.EmitScalarExpr(E->getArg(2)); + + llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID, {Val->getType()}); + llvm::Value *Call = CGF.Builder.CreateCall(F, Val); + + llvm::Value *SinResult = CGF.Builder.CreateExtractValue(Call, 0); + llvm::Value *CosResult = CGF.Builder.CreateExtractValue(Call, 1); + + QualType DestPtrType = E->getArg(1)->getType()->getPointeeType(); + LValue SinLV = CGF.MakeNaturalAlignAddrLValue(Dest0, DestPtrType); + LValue CosLV = CGF.MakeNaturalAlignAddrLValue(Dest1, DestPtrType); + + llvm::StoreInst *StoreSin = + CGF.Builder.CreateStore(SinResult, SinLV.getAddress()); + llvm::StoreInst *StoreCos = + CGF.Builder.CreateStore(CosResult, CosLV.getAddress()); + + // Mark the two stores as non-aliasing with each other. The order of stores + // emitted by this builtin is arbitrary, enforcing a particular order will + // prevent optimizations later on. + llvm::MDBuilder MDHelper(CGF.getLLVMContext()); + MDNode *Domain = MDHelper.createAnonymousAliasScopeDomain(); + MDNode *AliasScope = MDHelper.createAnonymousAliasScope(Domain); + MDNode *AliasScopeList = MDNode::get(Call->getContext(), AliasScope); + StoreSin->setMetadata(LLVMContext::MD_alias_scope, AliasScopeList); + StoreCos->setMetadata(LLVMContext::MD_noalias, AliasScopeList); +} + /// EmitFAbs - Emit a call to @llvm.fabs(). static Value *EmitFAbs(CodeGenFunction &CGF, Value *V) { Function *F = CGF.CGM.getIntrinsic(Intrinsic::fabs, V->getType()); @@ -3232,6 +3264,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( *this, E, Intrinsic::sinh, Intrinsic::experimental_constrained_sinh)); + case Builtin::BI__builtin_sincos: + case Builtin::BI__builtin_sincosf: + case Builtin::BI__builtin_sincosf16: + case Builtin::BI__builtin_sincosl: + case Builtin::BI__builtin_sincosf128: + emitSincosBuiltin(*this, E, Intrinsic::sincos); + return RValue::get(nullptr); + case Builtin::BIsqrt: case Builtin::BIsqrtf: case Builtin::BIsqrtl: diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index 0680b4828b6da..7db67ecba07c8 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -1169,8 +1169,9 @@ void AArch64TargetCodeGenInfo::checkFunctionABI( enum class ArmSMEInlinability : uint8_t { Ok = 0, ErrorCalleeRequiresNewZA = 1 << 0, - WarnIncompatibleStreamingModes = 1 << 1, - ErrorIncompatibleStreamingModes = 1 << 2, + ErrorCalleeRequiresNewZT0 = 1 << 1, + WarnIncompatibleStreamingModes = 1 << 2, + ErrorIncompatibleStreamingModes = 1 << 3, IncompatibleStreamingModes = WarnIncompatibleStreamingModes | ErrorIncompatibleStreamingModes, @@ -1198,9 +1199,12 @@ static ArmSMEInlinability GetArmSMEInlinability(const FunctionDecl *Caller, else Inlinability |= ArmSMEInlinability::WarnIncompatibleStreamingModes; } - if (auto *NewAttr = Callee->getAttr()) + if (auto *NewAttr = Callee->getAttr()) { if (NewAttr->isNewZA()) Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZA; + if (NewAttr->isNewZT0()) + Inlinability |= ArmSMEInlinability::ErrorCalleeRequiresNewZT0; + } return Inlinability; } @@ -1227,6 +1231,11 @@ void AArch64TargetCodeGenInfo::checkFunctionCallABIStreaming( ArmSMEInlinability::ErrorCalleeRequiresNewZA) CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_za) << Callee->getDeclName(); + + if ((Inlinability & ArmSMEInlinability::ErrorCalleeRequiresNewZT0) == + ArmSMEInlinability::ErrorCalleeRequiresNewZT0) + CGM.getDiags().Report(CallLoc, diag::err_function_always_inline_new_zt0) + << Callee->getDeclName(); } // If the target does not have floating-point registers, but we are using a diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 56ad0503a11ab..fa07e68c55835 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -537,7 +537,11 @@ AMDGPUTargetCodeGenInfo::getLLVMSyncScopeID(const LangOptions &LangOpts, break; } - if (Ordering != llvm::AtomicOrdering::SequentiallyConsistent) { + // OpenCL assumes by default that atomic scopes are per-address space for + // non-sequentially consistent operations. + if (Scope >= SyncScope::OpenCLWorkGroup && + Scope <= SyncScope::OpenCLSubGroup && + Ordering != llvm::AtomicOrdering::SequentiallyConsistent) { if (!Name.empty()) Name = Twine(Twine(Name) + Twine("-")).str(); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 945174ca9c586..e18e9a6fcd074 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1582,7 +1582,10 @@ class AnnotatingParser { return false; break; case tok::l_brace: - if (Style.Language == FormatStyle::LK_TextProto) { + if (IsCpp) { + if (Tok->is(TT_RequiresExpressionLBrace)) + Line.Type = LT_RequiresExpression; + } else if (Style.Language == FormatStyle::LK_TextProto) { FormatToken *Previous = Tok->getPreviousNonComment(); if (Previous && Previous->isNot(TT_DictLiteral)) Previous->setType(TT_SelectorName); @@ -2024,8 +2027,11 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } - if (Line.Type == LT_AccessModifier) - return LT_AccessModifier; + if (const auto Type = Line.Type; Type == LT_AccessModifier || + Type == LT_RequiresExpression || + Type == LT_SimpleRequirement) { + return Type; + } if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) @@ -3102,8 +3108,10 @@ class AnnotatingParser { } } - if (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement) + if (Line.Type == LT_SimpleRequirement || + (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) { return TT_BinaryOperator; + } return TT_PointerOrReference; } @@ -3693,8 +3701,15 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { if (!Line.Children.empty()) { ScopeStack.push_back(ST_ChildBlock); - for (auto &Child : Line.Children) + const bool InRequiresExpression = Line.Type == LT_RequiresExpression; + for (auto &Child : Line.Children) { + if (InRequiresExpression && + !Child->First->isOneOf(tok::kw_typename, tok::kw_requires, + TT_CompoundRequirementLBrace)) { + Child->Type = LT_SimpleRequirement; + } annotate(*Child); + } // ScopeStack can become empty if Child has an unmatched `}`. if (!ScopeStack.empty()) ScopeStack.pop_back(); diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 1a250e94d97c5..fa15517042f25 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -33,6 +33,8 @@ enum LineType { LT_VirtualFunctionDecl, LT_ArrayOfStructInitializer, LT_CommentAbovePPDirective, + LT_RequiresExpression, + LT_SimpleRequirement, }; enum ScopeType { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4a6027943072c..7fa9322e7551f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -7230,6 +7230,10 @@ void ASTWriter::CompletedImplicitDefinition(const FunctionDecl *D) { if (!D->isFromASTFile()) return; // Declaration not imported from PCH. + // The function definition may not have a body due to parsing errors. + if (!D->doesThisDeclarationHaveABody()) + return; + // Implicit function decl from a PCH was defined. DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } @@ -7249,6 +7253,10 @@ void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { if (!D->isFromASTFile()) return; + // The function definition may not have a body due to parsing errors. + if (!D->doesThisDeclarationHaveABody()) + return; + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index f21e5c3ad7bd7..738b6a175ce6d 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -170,9 +170,8 @@ SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { - SD = new (BPAlloc) SymbolRegionValue(SymbolCounter, R); + SD = Alloc.make(R); DataSet.InsertNode(SD, InsertPos); - ++SymbolCounter; } return cast(SD); @@ -188,9 +187,8 @@ const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E, void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { - SD = new (BPAlloc) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag); + SD = Alloc.make(E, LCtx, T, Count, SymbolTag); DataSet.InsertNode(SD, InsertPos); - ++SymbolCounter; } return cast(SD); @@ -204,9 +202,8 @@ SymbolManager::getDerivedSymbol(SymbolRef parentSymbol, void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { - SD = new (BPAlloc) SymbolDerived(SymbolCounter, parentSymbol, R); + SD = Alloc.make(parentSymbol, R); DataSet.InsertNode(SD, InsertPos); - ++SymbolCounter; } return cast(SD); @@ -219,9 +216,8 @@ SymbolManager::getExtentSymbol(const SubRegion *R) { void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { - SD = new (BPAlloc) SymbolExtent(SymbolCounter, R); + SD = Alloc.make(R); DataSet.InsertNode(SD, InsertPos); - ++SymbolCounter; } return cast(SD); @@ -236,9 +232,8 @@ SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, void *InsertPos; SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); if (!SD) { - SD = new (BPAlloc) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag); + SD = Alloc.make(R, S, T, LCtx, Count, SymbolTag); DataSet.InsertNode(SD, InsertPos); - ++SymbolCounter; } return cast(SD); @@ -252,7 +247,7 @@ SymbolManager::getCastSymbol(const SymExpr *Op, void *InsertPos; SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); if (!data) { - data = new (BPAlloc) SymbolCast(Op, From, To); + data = Alloc.make(Op, From, To); DataSet.InsertNode(data, InsertPos); } @@ -268,7 +263,7 @@ const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); if (!data) { - data = new (BPAlloc) SymIntExpr(lhs, op, v, t); + data = Alloc.make(lhs, op, v, t); DataSet.InsertNode(data, InsertPos); } @@ -284,7 +279,7 @@ const IntSymExpr *SymbolManager::getIntSymExpr(APSIntPtr lhs, SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); if (!data) { - data = new (BPAlloc) IntSymExpr(lhs, op, rhs, t); + data = Alloc.make(lhs, op, rhs, t); DataSet.InsertNode(data, InsertPos); } @@ -301,7 +296,7 @@ const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); if (!data) { - data = new (BPAlloc) SymSymExpr(lhs, op, rhs, t); + data = Alloc.make(lhs, op, rhs, t); DataSet.InsertNode(data, InsertPos); } @@ -316,7 +311,7 @@ const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand, void *InsertPos; SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); if (!data) { - data = new (BPAlloc) UnarySymExpr(Operand, Opc, T); + data = Alloc.make(Operand, Opc, T); DataSet.InsertNode(data, InsertPos); } diff --git a/clang/test/Analysis/dump_egraph.cpp b/clang/test/Analysis/dump_egraph.cpp index d1229b2634674..13459699a06f6 100644 --- a/clang/test/Analysis/dump_egraph.cpp +++ b/clang/test/Analysis/dump_egraph.cpp @@ -21,7 +21,7 @@ void foo() { // CHECK: \"location_context\": \"#0 Call\", \"calling\": \"T::T\", \"location\": \{ \"line\": 15, \"column\": 5, \"file\": \"{{.*}}dump_egraph.cpp\" \}, \"items\": [\l        \{ \"init_id\": {{[0-9]+}}, \"kind\": \"construct into member variable\", \"argument_index\": null, \"pretty\": \"s\", \"value\": \"&t.s\" -// CHECK: \"cluster\": \"t\", \"pointer\": \"{{0x[0-9a-f]+}}\", \"items\": [\l        \{ \"kind\": \"Default\", \"offset\": 0, \"value\": \"conj_$2\{int, LC5, no stmt, #1\}\" +// CHECK: \"cluster\": \"t\", \"pointer\": \"{{0x[0-9a-f]+}}\", \"items\": [\l        \{ \"kind\": \"Default\", \"offset\": 0, \"value\": \"conj_$3\{int, LC5, no stmt, #1\}\" // CHECK: \"dynamic_types\": [\l      \{ \"region\": \"HeapSymRegion\{conj_$1\{S *, LC1, S{{[0-9]+}}, #1\}\}\", \"dyn_type\": \"S\", \"sub_classable\": false \}\l diff --git a/clang/test/Analysis/expr-inspection-printState-diseq-info.c b/clang/test/Analysis/expr-inspection-printState-diseq-info.c index c5c31785a600e..515fcbbd43079 100644 --- a/clang/test/Analysis/expr-inspection-printState-diseq-info.c +++ b/clang/test/Analysis/expr-inspection-printState-diseq-info.c @@ -18,17 +18,17 @@ void test_disequality_info(int e0, int b0, int b1, int c0) { // CHECK-NEXT: { // CHECK-NEXT: "class": [ "(reg_$0) - 2" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "reg_$2" ]] + // CHECK-NEXT: [ "reg_$7" ]] // CHECK-NEXT: }, // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "reg_$2" ], + // CHECK-NEXT: "class": [ "reg_$15" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "(reg_$0) - 2" ], - // CHECK-NEXT: [ "reg_$3" ]] + // CHECK-NEXT: [ "reg_$7" ]] // CHECK-NEXT: }, // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "reg_$3" ], + // CHECK-NEXT: "class": [ "reg_$7" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "reg_$2" ]] + // CHECK-NEXT: [ "(reg_$0) - 2" ], + // CHECK-NEXT: [ "reg_$15" ]] // CHECK-NEXT: } // CHECK-NEXT: ], diff --git a/clang/test/Analysis/expr-inspection-printState-eq-classes.c b/clang/test/Analysis/expr-inspection-printState-eq-classes.c index 38e23d6e83826..19cc13735ab5a 100644 --- a/clang/test/Analysis/expr-inspection-printState-eq-classes.c +++ b/clang/test/Analysis/expr-inspection-printState-eq-classes.c @@ -16,6 +16,6 @@ void test_equivalence_classes(int a, int b, int c, int d) { } // CHECK: "equivalence_classes": [ -// CHECK-NEXT: [ "(reg_$0) != (reg_$2)" ], -// CHECK-NEXT: [ "reg_$0", "reg_$2", "reg_$3" ] +// CHECK-NEXT: [ "(reg_$0) != (reg_$5)" ], +// CHECK-NEXT: [ "reg_$0", "reg_$20", "reg_$5" ] // CHECK-NEXT: ], diff --git a/clang/test/Analysis/ptr-arith.cpp b/clang/test/Analysis/ptr-arith.cpp index a1264a1f04839..ec1c75c0c4063 100644 --- a/clang/test/Analysis/ptr-arith.cpp +++ b/clang/test/Analysis/ptr-arith.cpp @@ -139,10 +139,10 @@ struct parse_t { int parse(parse_t *p) { unsigned copy = p->bits2; clang_analyzer_dump(copy); - // expected-warning@-1 {{reg_$1},0 S64b,struct Bug_55934::parse_t}.bits2>}} + // expected-warning@-1 {{reg_$2},0 S64b,struct Bug_55934::parse_t}.bits2>}} header *bits = (header *)© clang_analyzer_dump(bits->b); - // expected-warning@-1 {{derived_$2{reg_$1},0 S64b,struct Bug_55934::parse_t}.bits2>,Element{copy,0 S64b,struct Bug_55934::header}.b}}} + // expected-warning@-1 {{derived_$4{reg_$2},0 S64b,struct Bug_55934::parse_t}.bits2>,Element{copy,0 S64b,struct Bug_55934::header}.b}}} return bits->b; // no-warning } } // namespace Bug_55934 diff --git a/clang/test/Analysis/symbol-simplification-disequality-info.cpp b/clang/test/Analysis/symbol-simplification-disequality-info.cpp index 69238b583eb84..33b8f150f5d02 100644 --- a/clang/test/Analysis/symbol-simplification-disequality-info.cpp +++ b/clang/test/Analysis/symbol-simplification-disequality-info.cpp @@ -14,14 +14,14 @@ void test(int a, int b, int c, int d) { clang_analyzer_printState(); // CHECK: "disequality_info": [ // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "((reg_$0) + (reg_$1)) + (reg_$2)" ], + // CHECK-NEXT: "class": [ "((reg_$0) + (reg_$2)) + (reg_$5)" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "reg_$3" ]] + // CHECK-NEXT: [ "reg_$8" ]] // CHECK-NEXT: }, // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "reg_$3" ], + // CHECK-NEXT: "class": [ "reg_$8" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "((reg_$0) + (reg_$1)) + (reg_$2)" ]] + // CHECK-NEXT: [ "((reg_$0) + (reg_$2)) + (reg_$5)" ]] // CHECK-NEXT: } // CHECK-NEXT: ], @@ -32,14 +32,14 @@ void test(int a, int b, int c, int d) { clang_analyzer_printState(); // CHECK: "disequality_info": [ // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "(reg_$0) + (reg_$2)" ], + // CHECK-NEXT: "class": [ "(reg_$0) + (reg_$5)" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "reg_$3" ]] + // CHECK-NEXT: [ "reg_$8" ]] // CHECK-NEXT: }, // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "reg_$3" ], + // CHECK-NEXT: "class": [ "reg_$8" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "(reg_$0) + (reg_$2)" ]] + // CHECK-NEXT: [ "(reg_$0) + (reg_$5)" ]] // CHECK-NEXT: } // CHECK-NEXT: ], @@ -50,10 +50,10 @@ void test(int a, int b, int c, int d) { // CHECK-NEXT: { // CHECK-NEXT: "class": [ "reg_$0" ], // CHECK-NEXT: "disequal_to": [ - // CHECK-NEXT: [ "reg_$3" ]] + // CHECK-NEXT: [ "reg_$8" ]] // CHECK-NEXT: }, // CHECK-NEXT: { - // CHECK-NEXT: "class": [ "reg_$3" ], + // CHECK-NEXT: "class": [ "reg_$8" ], // CHECK-NEXT: "disequal_to": [ // CHECK-NEXT: [ "reg_$0" ]] // CHECK-NEXT: } diff --git a/clang/test/Analysis/symbol-simplification-fixpoint-one-iteration.cpp b/clang/test/Analysis/symbol-simplification-fixpoint-one-iteration.cpp index 73922d420a8c3..42e984762538e 100644 --- a/clang/test/Analysis/symbol-simplification-fixpoint-one-iteration.cpp +++ b/clang/test/Analysis/symbol-simplification-fixpoint-one-iteration.cpp @@ -13,10 +13,10 @@ void test(int a, int b, int c) { return; clang_analyzer_printState(); // CHECK: "constraints": [ - // CHECK-NEXT: { "symbol": "((reg_$0) + (reg_$1)) != (reg_$2)", "range": "{ [0, 0] }" } + // CHECK-NEXT: { "symbol": "((reg_$0) + (reg_$2)) != (reg_$5)", "range": "{ [0, 0] }" } // CHECK-NEXT: ], // CHECK-NEXT: "equivalence_classes": [ - // CHECK-NEXT: [ "(reg_$0) + (reg_$1)", "reg_$2" ] + // CHECK-NEXT: [ "(reg_$0) + (reg_$2)", "reg_$5" ] // CHECK-NEXT: ], // CHECK-NEXT: "disequality_info": null, @@ -25,12 +25,12 @@ void test(int a, int b, int c) { return; clang_analyzer_printState(); // CHECK: "constraints": [ - // CHECK-NEXT: { "symbol": "(reg_$0) != (reg_$2)", "range": "{ [0, 0] }" }, - // CHECK-NEXT: { "symbol": "reg_$1", "range": "{ [0, 0] }" } + // CHECK-NEXT: { "symbol": "(reg_$0) != (reg_$5)", "range": "{ [0, 0] }" }, + // CHECK-NEXT: { "symbol": "reg_$2", "range": "{ [0, 0] }" } // CHECK-NEXT: ], // CHECK-NEXT: "equivalence_classes": [ - // CHECK-NEXT: [ "(reg_$0) != (reg_$2)" ], - // CHECK-NEXT: [ "reg_$0", "reg_$2" ] + // CHECK-NEXT: [ "(reg_$0) != (reg_$5)" ], + // CHECK-NEXT: [ "reg_$0", "reg_$5" ] // CHECK-NEXT: ], // CHECK-NEXT: "disequality_info": null, diff --git a/clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp b/clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp index 679ed3fda7a7a..cffb5a70869eb 100644 --- a/clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp +++ b/clang/test/Analysis/symbol-simplification-fixpoint-two-iterations.cpp @@ -15,11 +15,11 @@ void test(int a, int b, int c, int d) { return; clang_analyzer_printState(); // CHECK: "constraints": [ - // CHECK-NEXT: { "symbol": "(((reg_$0) + (reg_$1)) + (reg_$2)) != (reg_$3)", "range": "{ [0, 0] }" }, - // CHECK-NEXT: { "symbol": "(reg_$2) + (reg_$1)", "range": "{ [0, 0] }" } + // CHECK-NEXT: { "symbol": "(((reg_$0) + (reg_$2)) + (reg_$5)) != (reg_$8)", "range": "{ [0, 0] }" }, + // CHECK-NEXT: { "symbol": "(reg_$5) + (reg_$2)", "range": "{ [0, 0] }" } // CHECK-NEXT: ], // CHECK-NEXT: "equivalence_classes": [ - // CHECK-NEXT: [ "((reg_$0) + (reg_$1)) + (reg_$2)", "reg_$3" ] + // CHECK-NEXT: [ "((reg_$0) + (reg_$2)) + (reg_$5)", "reg_$8" ] // CHECK-NEXT: ], // CHECK-NEXT: "disequality_info": null, @@ -28,14 +28,14 @@ void test(int a, int b, int c, int d) { return; clang_analyzer_printState(); // CHECK: "constraints": [ - // CHECK-NEXT: { "symbol": "(reg_$0) != (reg_$3)", "range": "{ [0, 0] }" }, - // CHECK-NEXT: { "symbol": "reg_$1", "range": "{ [0, 0] }" }, - // CHECK-NEXT: { "symbol": "reg_$2", "range": "{ [0, 0] }" } + // CHECK-NEXT: { "symbol": "(reg_$0) != (reg_$8)", "range": "{ [0, 0] }" }, + // CHECK-NEXT: { "symbol": "reg_$2", "range": "{ [0, 0] }" }, + // CHECK-NEXT: { "symbol": "reg_$5", "range": "{ [0, 0] }" } // CHECK-NEXT: ], // CHECK-NEXT: "equivalence_classes": [ - // CHECK-NEXT: [ "(reg_$0) != (reg_$3)" ], - // CHECK-NEXT: [ "reg_$0", "reg_$3" ], - // CHECK-NEXT: [ "reg_$2" ] + // CHECK-NEXT: [ "(reg_$0) != (reg_$8)" ], + // CHECK-NEXT: [ "reg_$0", "reg_$8" ], + // CHECK-NEXT: [ "reg_$5" ] // CHECK-NEXT: ], // CHECK-NEXT: "disequality_info": null, diff --git a/clang/test/Analysis/unary-sym-expr.c b/clang/test/Analysis/unary-sym-expr.c index 92e11b295bee7..64a01a956c442 100644 --- a/clang/test/Analysis/unary-sym-expr.c +++ b/clang/test/Analysis/unary-sym-expr.c @@ -11,9 +11,9 @@ int test(int x, int y) { clang_analyzer_dump(-x); // expected-warning{{-reg_$0}} clang_analyzer_dump(~x); // expected-warning{{~reg_$0}} int z = x + y; - clang_analyzer_dump(-z); // expected-warning{{-((reg_$0) + (reg_$1))}} - clang_analyzer_dump(-(x + y)); // expected-warning{{-((reg_$0) + (reg_$1))}} - clang_analyzer_dump(-x + y); // expected-warning{{(-reg_$0) + (reg_$1)}} + clang_analyzer_dump(-z); // expected-warning{{-((reg_$0) + (reg_$3))}} + clang_analyzer_dump(-(x + y)); // expected-warning{{-((reg_$0) + (reg_$3))}} + clang_analyzer_dump(-x + y); // expected-warning{{(-reg_$0) + (reg_$3)}} if (-x == 0) { clang_analyzer_eval(-x == 0); // expected-warning{{TRUE}} diff --git a/clang/test/CXX/drs/cwg0xx.cpp b/clang/test/CXX/drs/cwg0xx.cpp index 2e2e6d4e662d6..15f469440c66f 100644 --- a/clang/test/CXX/drs/cwg0xx.cpp +++ b/clang/test/CXX/drs/cwg0xx.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98,cxx98-14 -fexceptions -fcxx-exceptions -pedantic-errors -Wno-bind-to-temporary-copy +// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98,cxx98-14 -fexceptions -fcxx-exceptions -pedantic-errors // RUN: %clang_cc1 -std=c++11 %s -verify=expected,since-cxx11,cxx98-14,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple // RUN: %clang_cc1 -std=c++14 %s -verify=expected,since-cxx11,cxx98-14,cxx11-14 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple // RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple @@ -56,7 +56,7 @@ namespace cwg1 { // cwg1: no } } // namespace cwg1 -namespace cwg3 { // cwg3: yes +namespace cwg3 { // cwg3: 2.7 template struct A {}; template void f(T) { A a; } // #cwg3-f-T template void f(int); @@ -156,7 +156,7 @@ namespace cwg10 { // cwg10: dup 45 }; } // namespace cwg10 -namespace cwg11 { // cwg11: yes +namespace cwg11 { // cwg11: 2.7 template struct A : T { using typename T::U; U u; @@ -221,7 +221,7 @@ namespace cwg14 { // cwg14: 3.4 // expected-note@#cwg14-Y-U {{candidate found by name lookup is 'cwg14::Y::U'}} } // namespace cwg14 -namespace cwg15 { // cwg15: yes +namespace cwg15 { // cwg15: 2.7 template void f(int); // #cwg15-f-decl-first template void f(int = 0); // expected-error@-1 {{default arguments cannot be added to a function template that has already been declared}} @@ -250,7 +250,7 @@ namespace cwg16 { // cwg16: 2.8 }; } // namespace cwg16 -namespace cwg17 { // cwg17: yes +namespace cwg17 { // cwg17: 2.7 class A { int n; int f(); @@ -311,7 +311,7 @@ namespace cwg22 { // cwg22: sup 481 template struct Y; } // namespace cwg22 -namespace cwg23 { // cwg23: yes +namespace cwg23 { // cwg23: 2.7 template void f(T, T); // #cwg23-f-T-T template void f(T, int); // #cwg23-f-T-int void g() { f(0, 0); } @@ -322,7 +322,7 @@ namespace cwg23 { // cwg23: yes // cwg24: na -namespace cwg25 { // cwg25: yes +namespace cwg25 { // cwg25: 4 struct A { void f() throw(int); // since-cxx17-error@-1 {{ISO C++17 does not allow dynamic exception specifications}} @@ -357,7 +357,7 @@ namespace cwg25 { // cwg25: yes } } // namespace cwg25 -namespace cwg26 { // cwg26: yes +namespace cwg26 { // cwg26: 2.7 struct A { A(A, const A & = A()); }; // expected-error@-1 {{copy constructor must pass its first argument by reference}} struct B { @@ -377,7 +377,7 @@ namespace cwg26 { // cwg26: yes }; } // namespace cwg26 -namespace cwg27 { // cwg27: yes +namespace cwg27 { // cwg27: 2.7 enum E { e } n; E &m = true ? n : n; } // namespace cwg27 @@ -623,7 +623,7 @@ namespace example4 { // cwg37: sup 475 -namespace cwg38 { // cwg38: yes +namespace cwg38 { // cwg38: 2.7 template struct X {}; template X operator+(X a, X b) { return a; } template X operator+(X, X); @@ -709,22 +709,22 @@ namespace cwg39 { // cwg39: no // expected-error@#cwg39-sizeof {{unknown type name}} #if __cplusplus >= 201103L decltype(D::n) n; - /* expected-error@-1 + /* since-cxx11-error@-1 {{non-static member 'n' found in multiple base-class subobjects of type 'A': struct cwg39::PR5916::D -> B -> A struct cwg39::PR5916::D -> C -> A}} */ - // expected-note@#cwg39-A-n {{member found by ambiguous name lookup}} + // since-cxx11-note@#cwg39-A-n {{member found by ambiguous name lookup}} #endif } } // namespace cwg39 // cwg40: na -namespace cwg41 { // cwg41: yes +namespace cwg41 { // cwg41: 2.7 struct S f(S); } // namespace cwg41 -namespace cwg42 { // cwg42: yes +namespace cwg42 { // cwg42: 2.7 struct A { static const int k = 0; }; struct B : A { static const int k = A::k; }; } // namespace cwg42 @@ -738,7 +738,7 @@ namespace cwg44 { // cwg44: sup 727 }; } // namespace cwg44 -namespace cwg45 { // cwg45: yes +namespace cwg45 { // cwg45: 2.7 class A { class B {}; class C : B {}; @@ -746,7 +746,7 @@ namespace cwg45 { // cwg45: yes }; } // namespace cwg45 -namespace cwg46 { // cwg46: yes +namespace cwg46 { // cwg46: 2.7 template struct A { template struct B {}; }; template template struct A::B; // expected-error@-1 {{expected unqualified-id}} @@ -766,7 +766,7 @@ namespace cwg47 { // cwg47: sup 329 void g() { f(); } } // namespace cwg47 -namespace cwg48 { // cwg48: yes +namespace cwg48 { // cwg48: 2.7 namespace { struct S { static const int m = 0; @@ -808,7 +808,7 @@ namespace cwg49 { // cwg49: 2.8 // since-cxx17-note@#cwg49-q {{declared here}} } // namespace cwg49 -namespace cwg50 { // cwg50: yes +namespace cwg50 { // cwg50: 2.7 struct X; // #cwg50-X extern X *p; X *q = (X*)p; @@ -842,7 +842,7 @@ namespace cwg52 { // cwg52: 2.8 // expected-note@#cwg52-B {{declared private here}} } // namespace cwg52 -namespace cwg53 { // cwg53: yes +namespace cwg53 { // cwg53: 2.7 int n = 0; enum E { e } x = static_cast(n); } // namespace cwg53 @@ -901,12 +901,12 @@ namespace cwg54 { // cwg54: 2.8 // expected-error@-1 {{conversion from pointer to member of class 'cwg54::V' to pointer to member of class 'B' via virtual base 'cwg54::V' is not allowed}} } // namespace cwg54 -namespace cwg55 { // cwg55: yes +namespace cwg55 { // cwg55: 2.7 enum E { e = 5 }; static_assert(e + 1 == 6, ""); } // namespace cwg55 -namespace cwg56 { // cwg56: yes +namespace cwg56 { // cwg56: 2.7 struct A { typedef int T; // #cwg56-typedef-int-T-first typedef int T; @@ -933,7 +933,7 @@ namespace cwg58 { // cwg58: 3.1 #endif } // namespace cwg58 -namespace cwg59 { // cwg59: yes +namespace cwg59 { // cwg59: 2.7 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-volatile" template struct convert_to { operator T() const; }; @@ -990,7 +990,7 @@ namespace cwg59 { // cwg59: yes #pragma clang diagnostic pop } // namespace cwg59 -namespace cwg60 { // cwg60: yes +namespace cwg60 { // cwg60: 2.7 void f(int &); int &f(...); const int k = 0; @@ -1067,13 +1067,13 @@ namespace cwg62 { // cwg62: 2.9 } } // namespace cwg62 -namespace cwg63 { // cwg63: yes +namespace cwg63 { // cwg63: 2.7 template struct S { typename T::error e; }; extern S *p; void *q = p; } // namespace cwg63 -namespace cwg64 { // cwg64: yes +namespace cwg64 { // cwg64: 2.7 template void f(T); template void f(T*); template<> void f(int*); @@ -1136,7 +1136,7 @@ namespace cwg69 { // cwg69: 9 // cxx98-note@#cwg69-f {{non-type template argument refers to function here}} } // namespace cwg69 -namespace cwg70 { // cwg70: yes +namespace cwg70 { // cwg70: 2.7 template struct A {}; template int f(int (&)[I + J], A, A); int arr[7]; @@ -1150,31 +1150,31 @@ namespace cwg73 { // cwg73: sup 1652 #if __cplusplus >= 201103L int a, b; static_assert(&a + 1 != &b, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{comparison against pointer '&a + 1' that points past the end of a complete object has unspecified value}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{comparison against pointer '&a + 1' that points past the end of a complete object has unspecified value}} #endif } // namespace cwg73 -namespace cwg74 { // cwg74: yes +namespace cwg74 { // cwg74: 2.7 enum E { k = 5 }; int (*p)[k] = new int[k][k]; } // namespace cwg74 -namespace cwg75 { // cwg75: yes +namespace cwg75 { // cwg75: 2.7 struct S { static int n = 0; // expected-error@-1 {{non-const static data member must be initialized out of line}} }; } // namespace cwg75 -namespace cwg76 { // cwg76: yes +namespace cwg76 { // cwg76: 2.7 const volatile int n = 1; static_assert(n, ""); // expected-error@-1 {{static assertion expression is not an integral constant expression}} // expected-note@-2 {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}} } // namespace cwg76 -namespace cwg77 { // cwg77: yes +namespace cwg77 { // cwg77: 2.7 struct A { struct B {}; friend struct B; @@ -1213,13 +1213,13 @@ namespace cwg80 { // cwg80: 2.9 // cwg81: na // cwg82: dup 48 -namespace cwg83 { // cwg83: yes +namespace cwg83 { // cwg83: 2.7 int &f(const char*); char &f(char *); int &k = f("foo"); } // namespace cwg83 -namespace cwg84 { // cwg84: yes +namespace cwg84 { // cwg84: 2.7 struct B; struct A { operator B() const; }; struct C {}; @@ -1255,14 +1255,14 @@ namespace cwg85 { // cwg85: 3.4 enum E1 : int; enum E1 : int { e1 }; // #cwg85-E1-def enum E1 : int; - // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#cwg85-E1-def {{previous declaration is here}} + // since-cxx11-error@-1 {{class member cannot be redeclared}} + // since-cxx11-note@#cwg85-E1-def {{previous declaration is here}} enum class E2; enum class E2 { e2 }; // #cwg85-E2-def enum class E2; - // expected-error@-1 {{class member cannot be redeclared}} - // expected-note@#cwg85-E2-def {{previous declaration is here}} + // since-cxx11-error@-1 {{class member cannot be redeclared}} + // since-cxx11-note@#cwg85-E2-def {{previous declaration is here}} #endif }; @@ -1299,7 +1299,7 @@ namespace cwg88 { // cwg88: 2.8 // cwg89: na -namespace cwg90 { // cwg90: yes +namespace cwg90 { // cwg90: 2.7 struct A { template friend void cwg90_f(T); }; @@ -1333,7 +1333,7 @@ namespace cwg90 { // cwg90: yes } } // namespace cwg90 -namespace cwg91 { // cwg91: yes +namespace cwg91 { // cwg91: 2.7 union U { friend int f(U); }; int k = f(U()); } // namespace cwg91 @@ -1383,7 +1383,7 @@ namespace cwg92 { // cwg92: 4 c++17 // cwg93: na -namespace cwg94 { // cwg94: yes +namespace cwg94 { // cwg94: 2.7 struct A { static const int n = 5; }; int arr[A::n]; } // namespace cwg94 @@ -1426,14 +1426,14 @@ namespace cwg96 { // cwg96: sup P1787 } } // namespace cwg96 -namespace cwg97 { // cwg97: yes +namespace cwg97 { // cwg97: 2.7 struct A { static const int a = false; static const int b = !a; }; } // namespace cwg97 -namespace cwg98 { // cwg98: yes +namespace cwg98 { // cwg98: 2.7 void test(int n) { switch (n) { try { // #cwg98-try diff --git a/clang/test/CXX/drs/cwg14xx.cpp b/clang/test/CXX/drs/cwg14xx.cpp index 149468eb292c9..51bc9614299a5 100644 --- a/clang/test/CXX/drs/cwg14xx.cpp +++ b/clang/test/CXX/drs/cwg14xx.cpp @@ -78,7 +78,7 @@ namespace cwg1432 { // cwg1432: 16 #endif } // namespace cwg1432 -namespace cwg1443 { // cwg1443: yes +namespace cwg1443 { // cwg1443: 2.7 struct A { int i; A() { void foo(int=i); } @@ -93,7 +93,7 @@ struct A; void f() { constexpr A* a = nullptr; constexpr int p = &*a; - // expected-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}} + // since-cxx11-error@-1 {{cannot initialize a variable of type 'const int' with an rvalue of type 'A *'}} constexpr A *p2 = &*a; } @@ -108,27 +108,27 @@ namespace cwg1460 { // cwg1460: 3.5 namespace DRExample { union A { union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} constexpr A() {} }; constexpr A a = A(); union B { union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} constexpr B() = default; }; constexpr B b = B(); union C { union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} union {}; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} }; constexpr C c = C(); #if __cplusplus >= 201403L @@ -141,7 +141,7 @@ namespace cwg1460 { // cwg1460: 3.5 union B { int n; }; // #cwg1460-B union C { int n = 0; }; struct D { union {}; }; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} struct E { union { int n; }; }; // #cwg1460-E struct F { union { int n = 0; }; }; @@ -173,7 +173,7 @@ namespace cwg1460 { // cwg1460: 3.5 // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} union C { int n = 0; constexpr C() = default; }; struct D { union {}; constexpr D() = default; }; - // expected-error@-1 {{declaration does not declare anything}} + // since-cxx11-error@-1 {{declaration does not declare anything}} struct E { union { int n; }; constexpr E() = default; }; // cxx11-17-error@-1 {{defaulted definition of default constructor cannot be marked constexpr}} struct F { union { int n = 0; }; constexpr F() = default; }; @@ -222,8 +222,8 @@ namespace cwg1460 { // cwg1460: 3.5 union G { int a = 0; // #cwg1460-G-a int b = 0; - // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#cwg1460-G-a {{previous initialization is here}} + // since-cxx11-error@-1 {{initializing multiple members of union}} + // since-cxx11-note@#cwg1460-G-a {{previous initialization is here}} }; union H { union { @@ -231,16 +231,16 @@ namespace cwg1460 { // cwg1460: 3.5 }; union { int b = 0; - // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#cwg1460-H-a {{previous initialization is here}} + // since-cxx11-error@-1 {{initializing multiple members of union}} + // since-cxx11-note@#cwg1460-H-a {{previous initialization is here}} }; }; struct I { union { int a = 0; // #cwg1460-I-a int b = 0; - // expected-error@-1 {{initializing multiple members of union}} - // expected-note@#cwg1460-I-a {{previous initialization is here}} + // since-cxx11-error@-1 {{initializing multiple members of union}} + // since-cxx11-note@#cwg1460-I-a {{previous initialization is here}} }; }; struct J { @@ -264,23 +264,23 @@ namespace cwg1460 { // cwg1460: 3.5 }; static_assert(B().a == 1, ""); static_assert(B().b == 2, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} static_assert(B('x').a == 0, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(B('x').b == 4, ""); static_assert(B(123).b == 2, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} static_assert(B(123).c == 3, ""); static_assert(B("").a == 1, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(B("").b == 2, ""); static_assert(B("").c == 3, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} struct C { union { int a, b = 2, c; }; @@ -294,54 +294,54 @@ namespace cwg1460 { // cwg1460: 3.5 static_assert(C().a == 1, ""); static_assert(C().b == 2, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'b' of union with active member 'a' is not allowed in a constant expression}} static_assert(C().d == 4, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C().e == 5, ""); static_assert(C('x').b == 2, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'b' of union with active member 'c' is not allowed in a constant expression}} static_assert(C('x').c == 3, ""); static_assert(C('x').d == 4, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C('x').e == 5, ""); static_assert(C(1).b == 2, ""); static_assert(C(1).c == 3, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} static_assert(C(1).d == 4, ""); static_assert(C(1).e == 5, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'e' of union with active member 'd' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'e' of union with active member 'd' is not allowed in a constant expression}} static_assert(C(1.f).b == 2, ""); static_assert(C(1.f).c == 3, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} static_assert(C(1.f).e == 5, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'e' of union with active member 'f' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'e' of union with active member 'f' is not allowed in a constant expression}} static_assert(C(1.f).f == 6, ""); static_assert(C("").a == 1, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'a' of union with active member 'b' is not allowed in a constant expression}} static_assert(C("").b == 2, ""); static_assert(C("").c == 3, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'c' of union with active member 'b' is not allowed in a constant expression}} static_assert(C("").d == 4, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'd' of union with active member 'e' is not allowed in a constant expression}} static_assert(C("").e == 5, ""); static_assert(C("").f == 6, ""); - // expected-error@-1 {{static assertion expression is not an integral constant expression}} - // expected-note@-2 {{read of member 'f' of union with active member 'e' is not allowed in a constant expression}} + // since-cxx11-error@-1 {{static assertion expression is not an integral constant expression}} + // since-cxx11-note@-2 {{read of member 'f' of union with active member 'e' is not allowed in a constant expression}} struct D; extern const D d; diff --git a/clang/test/CXX/drs/cwg15xx.cpp b/clang/test/CXX/drs/cwg15xx.cpp index d10890ee3fd15..30ec63999ca28 100644 --- a/clang/test/CXX/drs/cwg15xx.cpp +++ b/clang/test/CXX/drs/cwg15xx.cpp @@ -355,7 +355,7 @@ namespace cwg1560 { // cwg1560: 3.5 const X &x = true ? get() : throw 0; } // namespace cwg1560 -namespace cwg1563 { // cwg1563: yes +namespace cwg1563 { // cwg1563: 3.1 #if __cplusplus >= 201103L double bar(double) { return 0.0; } float bar(float) { return 0.0f; } diff --git a/clang/test/CXX/drs/cwg17xx.cpp b/clang/test/CXX/drs/cwg17xx.cpp index 04bf637543a29..8c4f916a606a4 100644 --- a/clang/test/CXX/drs/cwg17xx.cpp +++ b/clang/test/CXX/drs/cwg17xx.cpp @@ -225,8 +225,8 @@ namespace cwg1778 { // cwg1778: 9 // cwg1779 is in cwg177x.cpp -namespace cwg1794 { // cwg1794: yes - // NB: dup 1710 +namespace cwg1794 { // cwg1794: 2.7 + // NB: dup 1710 #if __cplusplus >= 201103L template