diff --git a/clang/include/clang/AST/APValue.h b/clang/include/clang/AST/APValue.h index a6b0fc51cb5f..d26647306842 100644 --- a/clang/include/clang/AST/APValue.h +++ b/clang/include/clang/AST/APValue.h @@ -24,52 +24,14 @@ namespace clang { class AddrLabelExpr; class ASTContext; class CharUnits; - class CXXRecordDecl; - class Decl; class DiagnosticBuilder; class Expr; class FieldDecl; - struct PrintingPolicy; - class Type; + class Decl; class ValueDecl; + class CXXRecordDecl; + class QualType; -/// Symbolic representation of typeid(T) for some type T. -class TypeInfoLValue { - const Type *T; - -public: - TypeInfoLValue() : T() {} - explicit TypeInfoLValue(const Type *T); - - const Type *getType() const { return T; } - explicit operator bool() const { return T; } - - void *getOpaqueValue() { return const_cast(T); } - static TypeInfoLValue getFromOpaqueValue(void *Value) { - TypeInfoLValue V; - V.T = reinterpret_cast(Value); - return V; - } - - void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy) const; -}; -} - -namespace llvm { -template<> struct PointerLikeTypeTraits { - static void *getAsVoidPointer(clang::TypeInfoLValue V) { - return V.getOpaqueValue(); - } - static clang::TypeInfoLValue getFromVoidPointer(void *P) { - return clang::TypeInfoLValue::getFromOpaqueValue(P); - } - // Validated by static_assert in APValue.cpp; hardcoded to avoid needing - // to include Type.h. - static constexpr int NumLowBitsAvailable = 3; -}; -} - -namespace clang { /// APValue - This class implements a discriminated union of [uninitialized] /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset], /// [Vector: N * APValue], [Array: N * APValue] @@ -95,18 +57,13 @@ public: class LValueBase { public: - typedef llvm::PointerUnion - PtrTy; + typedef llvm::PointerUnion PtrTy; - LValueBase() : Local{} {} + LValueBase() : CallIndex(0), Version(0) {} template - LValueBase(T P, unsigned I = 0, unsigned V = 0) : Ptr(P), Local{I, V} { - assert(!is() && - "don't use this constructor to form a type_info lvalue"); - } - - static LValueBase getTypeInfo(TypeInfoLValue LV, QualType TypeInfo); + LValueBase(T P, unsigned I = 0, unsigned V = 0) + : Ptr(P), CallIndex(I), Version(V) {} template bool is() const { return Ptr.is(); } @@ -121,15 +78,28 @@ public: bool isNull() const; - explicit operator bool() const; + explicit operator bool () const; - PtrTy getPointer() const { return Ptr; } + PtrTy getPointer() const { + return Ptr; + } - unsigned getCallIndex() const; - unsigned getVersion() const; - QualType getTypeInfoType() const; + unsigned getCallIndex() const { + return CallIndex; + } - friend bool operator==(const LValueBase &LHS, const LValueBase &RHS); + void setCallIndex(unsigned Index) { + CallIndex = Index; + } + + unsigned getVersion() const { + return Version; + } + + friend bool operator==(const LValueBase &LHS, const LValueBase &RHS) { + return LHS.Ptr == RHS.Ptr && LHS.CallIndex == RHS.CallIndex && + LHS.Version == RHS.Version; + } friend bool operator!=(const LValueBase &LHS, const LValueBase &RHS) { return !(LHS == RHS); } @@ -137,14 +107,7 @@ public: private: PtrTy Ptr; - struct LocalState { - unsigned CallIndex, Version; - }; - union { - LocalState Local; - /// The type std::type_info, if this is a TypeInfoLValue. - void *TypeInfoType; - }; + unsigned CallIndex, Version; }; /// A FieldDecl or CXXRecordDecl, along with a flag indicating whether we diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 3e9ebbbabd45..17256fbd80b0 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -160,9 +160,6 @@ def note_constexpr_access_static_temporary : Note< "dynamic_cast 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|assignment to|increment of|decrement of|member call on|" - "dynamic_cast of}0 object '%1' whose value is not known">; def note_constexpr_modify_global : Note< "a constant expression cannot modify an object that is visible outside " "that expression">; diff --git a/clang/lib/AST/APValue.cpp b/clang/lib/AST/APValue.cpp index 83b0fb5e1a2c..e7902e687800 100644 --- a/clang/lib/AST/APValue.cpp +++ b/clang/lib/AST/APValue.cpp @@ -20,56 +20,6 @@ #include "llvm/Support/raw_ostream.h" using namespace clang; -/// The identity of a type_info object depends on the canonical unqualified -/// type only. -TypeInfoLValue::TypeInfoLValue(const Type *T) - : T(T->getCanonicalTypeUnqualified().getTypePtr()) {} - -void TypeInfoLValue::print(llvm::raw_ostream &Out, - const PrintingPolicy &Policy) const { - Out << "typeid("; - QualType(getType(), 0).print(Out, Policy); - Out << ")"; -} - -static_assert( - 1 << llvm::PointerLikeTypeTraits::NumLowBitsAvailable <= - alignof(const Type *), - "Type is insufficiently aligned"); - -APValue::LValueBase APValue::LValueBase::getTypeInfo(TypeInfoLValue LV, - QualType TypeInfo) { - LValueBase Base; - Base.Ptr = LV; - Base.TypeInfoType = TypeInfo.getAsOpaquePtr(); - return Base; -} - -unsigned APValue::LValueBase::getCallIndex() const { - return is() ? 0 : Local.CallIndex; -} - -unsigned APValue::LValueBase::getVersion() const { - return is() ? 0 : Local.Version; -} - -QualType APValue::LValueBase::getTypeInfoType() const { - assert(is() && "not a type_info lvalue"); - return QualType::getFromOpaquePtr(TypeInfoType); -} - -namespace clang { -bool operator==(const APValue::LValueBase &LHS, - const APValue::LValueBase &RHS) { - if (LHS.Ptr != RHS.Ptr) - return false; - if (LHS.is()) - return true; - return LHS.Local.CallIndex == RHS.Local.CallIndex && - LHS.Local.Version == RHS.Local.Version; -} -} - namespace { struct LVBase { APValue::LValueBase Base; @@ -110,8 +60,6 @@ llvm::DenseMapInfo::getTombstoneKey() { namespace clang { llvm::hash_code hash_value(const APValue::LValueBase &Base) { - if (Base.is()) - return llvm::hash_value(Base.getOpaqueValue()); return llvm::hash_combine(Base.getOpaqueValue(), Base.getCallIndex(), Base.getVersion()); } @@ -522,9 +470,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast()) Out << *VD; - else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); - } else { + else { assert(Base.get() != nullptr && "Expecting non-null Expr"); Base.get()->printPretty(Out, nullptr, @@ -549,9 +495,6 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast()) { Out << *VD; ElemTy = VD->getType(); - } else if (TypeInfoLValue TI = Base.dyn_cast()) { - TI.print(Out, Ctx.getPrintingPolicy()); - ElemTy = Base.getTypeInfoType(); } else { const Expr *E = Base.get(); assert(E != nullptr && "Expecting non-null Expr"); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e41264e55e4c..29b6d12c2f27 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -87,9 +87,6 @@ namespace { return D->getType(); } - if (TypeInfoLValue TI = B.dyn_cast()) - return B.getTypeInfoType(); - const Expr *Base = B.get(); // For a materialized temporary, the type of the temporary we materialized @@ -1786,9 +1783,6 @@ static bool IsGlobalLValue(APValue::LValueBase B) { return isa(D); } - if (B.is()) - return true; - const Expr *E = B.get(); switch (E->getStmtClass()) { default: @@ -1806,6 +1800,7 @@ static bool IsGlobalLValue(APValue::LValueBase B) { case Expr::PredefinedExprClass: case Expr::ObjCStringLiteralClass: case Expr::ObjCEncodeExprClass: + case Expr::CXXTypeidExprClass: case Expr::CXXUuidofExprClass: return true; case Expr::ObjCBoxedExprClass: @@ -1883,9 +1878,9 @@ static void NoteLValueLocation(EvalInfo &Info, APValue::LValueBase Base) { const ValueDecl *VD = Base.dyn_cast(); if (VD) Info.Note(VD->getLocation(), diag::note_declared_at); - else if (const Expr *E = Base.dyn_cast()) - Info.Note(E->getExprLoc(), diag::note_constexpr_temporary_here); - // We have no information to show for a typeid(T) object. + else + Info.Note(Base.get()->getExprLoc(), + diag::note_constexpr_temporary_here); } /// Check that this reference or pointer core constant expression is a valid @@ -3409,7 +3404,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, if (!Frame) { if (const MaterializeTemporaryExpr *MTE = - dyn_cast_or_null(Base)) { + dyn_cast(Base)) { assert(MTE->getStorageDuration() == SD_Static && "should have a frame for a non-global materialized temporary"); @@ -3444,13 +3439,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, const Expr *E, } else { if (!IsAccess) return CompleteObject(LVal.getLValueBase(), nullptr, BaseType); - APValue Val; - LVal.moveInto(Val); - Info.FFDiag(E, diag::note_constexpr_access_unreadable_object) - << AK - << Val.getAsString(Info.Ctx, - Info.Ctx.getLValueReferenceType(LValType)); - NoteLValueLocation(Info, LVal.Base); + Info.FFDiag(E); return CompleteObject(); } } else { @@ -5788,13 +5777,13 @@ public: // - Literals // * CompoundLiteralExpr in C (and in global scope in C++) // * StringLiteral +// * CXXTypeidExpr // * PredefinedExpr // * ObjCStringLiteralExpr // * ObjCEncodeExpr // * AddrLabelExpr // * BlockExpr // * CallExpr for a MakeStringConstant builtin -// - typeid(T) expressions, as TypeInfoLValues // - Locals and temporaries // * MaterializeTemporaryExpr // * Any Expr, with a CallIndex indicating the function in which the temporary @@ -6029,14 +6018,8 @@ LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { } bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) { - if (!E->isPotentiallyEvaluated()) { - TypeInfoLValue TypeInfo; - if (E->isTypeOperand()) - TypeInfo = TypeInfoLValue(E->getTypeOperand(Info.Ctx).getTypePtr()); - else - TypeInfo = TypeInfoLValue(E->getExprOperand()->getType().getTypePtr()); - return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType())); - } + if (!E->isPotentiallyEvaluated()) + return Success(E); Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic) << E->getExprOperand()->getType() @@ -6632,11 +6615,9 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, if (const ValueDecl *VD = OffsetResult.Base.dyn_cast()) { BaseAlignment = Info.Ctx.getDeclAlign(VD); - } else if (const Expr *E = OffsetResult.Base.dyn_cast()) { - BaseAlignment = GetAlignOfExpr(Info, E, UETT_AlignOf); } else { - BaseAlignment = GetAlignOfType( - Info, OffsetResult.Base.getTypeInfoType(), UETT_AlignOf); + BaseAlignment = GetAlignOfExpr( + Info, OffsetResult.Base.get(), UETT_AlignOf); } if (BaseAlignment < Align) { @@ -8354,10 +8335,6 @@ static bool EvaluateBuiltinConstantPForLValue(const APValue &LV) { if (!isa(E)) return false; return LV.getLValueOffset().isZero(); - } else if (Base.is()) { - // Surprisingly, GCC considers __builtin_constant_p(&typeid(int)) to - // evaluate to true. - return true; } else { // Any other base is not constant enough for GCC. return false; @@ -8422,8 +8399,6 @@ static QualType getObjectType(APValue::LValueBase B) { } else if (const Expr *E = B.get()) { if (isa(E)) return E->getType(); - } else if (B.is()) { - return B.getTypeInfoType(); } return QualType(); diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 70904b192a39..dd71cf02d957 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1735,17 +1735,6 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { return nullptr; } - // Handle typeid(T). - if (TypeInfoLValue TI = base.dyn_cast()) { - llvm::Type *StdTypeInfoPtrTy = - CGM.getTypes().ConvertType(base.getTypeInfoType())->getPointerTo(); - llvm::Constant *TypeInfo = - CGM.GetAddrOfRTTIDescriptor(QualType(TI.getType(), 0)); - if (TypeInfo->getType() != StdTypeInfoPtrTy) - TypeInfo = llvm::ConstantExpr::getBitCast(TypeInfo, StdTypeInfoPtrTy); - return TypeInfo; - } - // Otherwise, it must be an expression. return Visit(base.get()); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 239b4ae7957e..b9d3ff8666f9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -6424,11 +6424,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- a string literal // -- the result of a typeid expression, or // -- a predefined __func__ variable - APValue::LValueBase Base = Value.getLValueBase(); - auto *VD = const_cast(Base.dyn_cast()); - if (Base && !VD) { - auto *E = Base.dyn_cast(); - if (E && isa(E)) { + if (auto *E = Value.getLValueBase().dyn_cast()) { + if (isa(E)) { Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts()); break; } @@ -6436,6 +6433,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, << Arg->getSourceRange(); return ExprError(); } + auto *VD = const_cast( + Value.getLValueBase().dyn_cast()); // -- a subobject if (Value.hasLValuePath() && Value.getLValuePath().size() == 1 && VD && VD->getType()->isArrayType() && diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp index 4e359681fa8d..a1e8c764354f 100644 --- a/clang/test/CXX/drs/dr19xx.cpp +++ b/clang/test/CXX/drs/dr19xx.cpp @@ -167,14 +167,9 @@ namespace dr1959 { // dr1959: 3.9 #endif } -namespace dr1968 { // dr1968: no +namespace dr1968 { // dr1968: yes #if __cplusplus >= 201103L - // FIXME: According to DR1968, both of these should be considered - // non-constant. - static_assert(&typeid(int) == &typeid(int), ""); - - constexpr const std::type_info *f() { return &typeid(int); } - static_assert(f() == f(), ""); + static_assert(&typeid(int) == &typeid(int), ""); // expected-error{{not an integral constant expression}} #endif } diff --git a/clang/test/Parser/MicrosoftExtensions.cpp b/clang/test/Parser/MicrosoftExtensions.cpp index 913645b6891b..63e8b608239e 100644 --- a/clang/test/Parser/MicrosoftExtensions.cpp +++ b/clang/test/Parser/MicrosoftExtensions.cpp @@ -138,8 +138,6 @@ typedef COM_CLASS_TEMPLATE_REF COM COM_CLASS_TEMPLATE_REF good_template_arg; COM_CLASS_TEMPLATE bad_template_arg; // expected-error {{non-type template argument of type 'const _GUID' is not a constant expression}} -// expected-note@-1 {{read of object '__uuidof(struct_with_uuid)' whose value is not known}} -// expected-note@-2 {{temporary created here}} namespace PR16911 { struct __declspec(uuid("{12345678-1234-1234-1234-1234567890aB}")) uuid; diff --git a/clang/test/SemaCXX/builtin-constant-p.cpp b/clang/test/SemaCXX/builtin-constant-p.cpp index f70676d250e0..21cbaf7c699a 100644 --- a/clang/test/SemaCXX/builtin-constant-p.cpp +++ b/clang/test/SemaCXX/builtin-constant-p.cpp @@ -130,8 +130,3 @@ constexpr int mutate6(bool mutate) { static_assert(mutate6(false) == 11); // Mutation of state outside __builtin_constant_p: evaluates to false. static_assert(mutate6(true) == 10); - -// GCC strangely returns true for the address of a type_info object, despite it -// not being a pointer to the start of a string literal. -namespace std { struct type_info; } -static_assert(__builtin_constant_p(&typeid(int))); diff --git a/clang/test/SemaCXX/typeid.cpp b/clang/test/SemaCXX/typeid.cpp index 4e696deee131..48fcce0b4924 100644 --- a/clang/test/SemaCXX/typeid.cpp +++ b/clang/test/SemaCXX/typeid.cpp @@ -6,7 +6,7 @@ void f() } namespace std { - struct type_info { const char *name; }; + class type_info; } void g() @@ -27,6 +27,3 @@ void h(int i) { typeid(V); // expected-error{{'typeid' of variably modified type 'char [i]'}} typeid(char [i]); // expected-error{{'typeid' of variably modified type 'char [i]'}} } - -// expected-note@+1 {{read of object 'typeid(int).name' whose value is not known}} -constexpr const char *name = typeid(int).name; // expected-error {{constant expression}} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 663fe584aacc..6592e834ebd8 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -11623,7 +11623,7 @@ and POD class 1968 NAD Address of typeid in constant expressions - No + Yes 1969