[clang] a2ac64d - Revert "Ensure that checkInitIsICE is called exactly once for every variable"
Zequan Wu via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 26 12:00:05 PDT 2020
Author: Zequan Wu
Date: 2020-10-26T11:59:55-07:00
New Revision: a2ac64dd905422ed84e273a98d846df022a5e2ec
URL: https://github.com/llvm/llvm-project/commit/a2ac64dd905422ed84e273a98d846df022a5e2ec
DIFF: https://github.com/llvm/llvm-project/commit/a2ac64dd905422ed84e273a98d846df022a5e2ec.diff
LOG: Revert "Ensure that checkInitIsICE is called exactly once for every variable"
This causing `Assertion Result && "Could not evaluate expression"' failed` at https://bugs.chromium.org/p/chromium/issues/detail?id=1142009
This reverts commit 76c0092665867a6defcd328ba0d0d976eb65d991.
Added:
Modified:
clang/include/clang/AST/Decl.h
clang/include/clang/Serialization/ASTRecordWriter.h
clang/lib/AST/ComparisonCategories.cpp
clang/lib/AST/Decl.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/CodeGen/enable_if.c
clang/test/OpenMP/threadprivate_codegen.cpp
clang/test/Sema/enable_if.c
clang/test/SemaCXX/constant-expression.cpp
clang/test/SemaCXX/i-c-e-cxx.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 5d4f18806ff4..0bbdfa2a9d52 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -835,14 +835,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
/// Initialization styles.
enum InitializationStyle {
- /// C-style initialization with assignment
CInit,
/// Call-style initialization (C++98)
- CallInit,
-
- /// Direct list-initialization (C++11)
- ListInit
};
/// Kinds of thread-local storage.
@@ -1262,15 +1257,14 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
/// constant expression, according to the relevant language standard.
/// This only checks properties of the declaration, and does not check
/// whether the initializer is in fact a constant expression.
- bool mightBeUsableInConstantExpressions(const ASTContext &C) const;
+ bool mightBeUsableInConstantExpressions(ASTContext &C) const;
/// Determine whether this variable's value can be used in a
/// constant expression, according to the relevant language standard,
/// including checking whether it was initialized by a constant expression.
- bool isUsableInConstantExpressions(const ASTContext &C) const;
+ bool isUsableInConstantExpressions(ASTContext &C) const;
EvaluatedStmt *ensureEvaluatedStmt() const;
- EvaluatedStmt *getEvaluatedStmt() const;
/// Attempt to evaluate the value of the initializer attached to this
/// declaration, and produce notes explaining why it cannot be evaluated.
diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h
index e362463b2309..edfcd9c52e2e 100644
--- a/clang/include/clang/Serialization/ASTRecordWriter.h
+++ b/clang/include/clang/Serialization/ASTRecordWriter.h
@@ -266,9 +266,6 @@ class ASTRecordWriter
void AddCXXDefinitionData(const CXXRecordDecl *D);
- /// Emit information about the initializer of a VarDecl.
- void AddVarDeclInit(const VarDecl *VD);
-
/// Write an OMPTraitInfo object.
void writeOMPTraitInfo(const OMPTraitInfo *TI);
diff --git a/clang/lib/AST/ComparisonCategories.cpp b/clang/lib/AST/ComparisonCategories.cpp
index 896050482644..6b6826c02a12 100644
--- a/clang/lib/AST/ComparisonCategories.cpp
+++ b/clang/lib/AST/ComparisonCategories.cpp
@@ -42,7 +42,7 @@ clang::getComparisonCategoryForBuiltinCmp(QualType T) {
bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const {
assert(VD && "must have var decl");
- if (!VD->isUsableInConstantExpressions(VD->getASTContext()))
+ if (!VD->checkInitIsICE())
return false;
// Before we attempt to get the value of the first field, ensure that we
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 80bc22b61b70..884cd177d18e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2277,7 +2277,7 @@ void VarDecl::setInit(Expr *I) {
Init = I;
}
-bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
+bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const {
const LangOptions &Lang = C.getLangOpts();
// OpenCL permits const integral variables to be used in constant
@@ -2314,7 +2314,7 @@ bool VarDecl::mightBeUsableInConstantExpressions(const ASTContext &C) const {
return Lang.CPlusPlus11 && isConstexpr();
}
-bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
+bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const {
// C++2a [expr.const]p3:
// A variable is usable in constant expressions after its initializing
// declaration is encountered...
@@ -2356,10 +2356,6 @@ EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
return Eval;
}
-EvaluatedStmt *VarDecl::getEvaluatedStmt() const {
- return Init.dyn_cast<EvaluatedStmt *>();
-}
-
APValue *VarDecl::evaluateValue() const {
SmallVector<PartialDiagnosticAt, 8> Notes;
return evaluateValueImpl(Notes, hasConstantInitialization());
@@ -2369,17 +2365,19 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
bool IsConstantInitialization) const {
EvaluatedStmt *Eval = ensureEvaluatedStmt();
- const auto *Init = cast<Expr>(Eval->Value);
- assert(!Init->isValueDependent());
-
// We only produce notes indicating why an initializer is non-constant the
// first time it is evaluated. FIXME: The notes won't always be emitted the
// first time we try evaluation, so might not be produced at all.
if (Eval->WasEvaluated)
return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated;
+ const auto *Init = cast<Expr>(Eval->Value);
+ assert(!Init->isValueDependent());
+
if (Eval->IsEvaluating) {
// FIXME: Produce a diagnostic for self-initialization.
+ Eval->CheckedICE = true;
+ Eval->IsICE = false;
return nullptr;
}
@@ -2407,11 +2405,18 @@ APValue *VarDecl::evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
Eval->IsEvaluating = false;
Eval->WasEvaluated = true;
+ // In C++11, we have determined whether the initializer was a constant
+ // expression as a side-effect.
+ if (getASTContext().getLangOpts().CPlusPlus11 && !Eval->CheckedICE) {
+ Eval->CheckedICE = true;
+ Eval->IsICE = Result && Notes.empty();
+ }
+
return Result ? &Eval->Evaluated : nullptr;
}
APValue *VarDecl::getEvaluatedValue() const {
- if (EvaluatedStmt *Eval = getEvaluatedStmt())
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
if (Eval->WasEvaluated)
return &Eval->Evaluated;
@@ -2617,7 +2622,7 @@ bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
QualType::DestructionKind
VarDecl::needsDestruction(const ASTContext &Ctx) const {
- if (EvaluatedStmt *Eval = getEvaluatedStmt())
+ if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
if (Eval->HasConstantDestruction)
return QualType::DK_none;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index fa4026b865fb..412cfeb8fd3d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -3362,6 +3362,7 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
!Info.getLangOpts().CPlusPlus11 && !VD->hasICEInitializer(Info.Ctx))) {
Info.CCEDiag(E, diag::note_constexpr_var_init_non_constant, 1) << VD;
NoteLValueLocation(Info, Base);
+ Info.addNotes(Notes);
}
// Never use the initializer of a weak variable, not even for constant
@@ -3376,6 +3377,11 @@ static bool evaluateVarDeclInit(EvalInfo &Info, const Expr *E,
return true;
}
+static bool IsConstNonVolatile(QualType T) {
+ Qualifiers Quals = T.getQualifiers();
+ return Quals.hasConst() && !Quals.hasVolatile();
+}
+
/// Get the base index of the given base class within an APValue representing
/// the given derived class.
static unsigned getBaseIndex(const CXXRecordDecl *Derived,
@@ -8187,12 +8193,6 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
return Success(VD);
}
- if (!Info.getLangOpts().CPlusPlus11) {
- Info.CCEDiag(E, diag::note_constexpr_ltor_non_integral, 1)
- << VD << VD->getType();
- Info.Note(VD->getLocation(), diag::note_declared_at);
- }
-
APValue *V;
if (!evaluateVarDeclInit(Info, E, VD, Frame, Version, V))
return false;
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 8ab80e66dec3..6e169cf35869 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -361,9 +361,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
return !VD->needsDestruction(getContext()) && InitDecl->evaluateValue();
// Otherwise, we need a thread wrapper unless we know that every
- // translation unit will emit the value as a constant. We rely on the
- // variable being constant-initialized in every translation unit if it's
- // constant-initialized in any translation unit, which isn't actually
+ // translation unit will emit the value as a constant. We rely on
+ // ICE-ness not varying between translation units, which isn't actually
// guaranteed by the standard but is necessary for sanity.
return InitDecl->hasConstantInitialization();
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 2bffd2a87d08..07b70de5a8d2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12958,14 +12958,18 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
// All the following checks are C++ only.
if (!getLangOpts().CPlusPlus) {
- // If this variable must be emitted, add it as an initializer for the
- // current module.
- if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
- Context.addModuleInitializer(ModuleScopes.back().Module, var);
- return;
+ // If this variable must be emitted, add it as an initializer for the
+ // current module.
+ if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
+ Context.addModuleInitializer(ModuleScopes.back().Module, var);
+ return;
}
+ if (auto *DD = dyn_cast<DecompositionDecl>(var))
+ CheckCompleteDecompositionDeclaration(DD);
+
QualType type = var->getType();
+ if (type->isDependentType()) return;
if (var->hasAttr<BlocksAttr>())
getCurFunction()->addByrefBlockVar(var);
@@ -13020,47 +13024,65 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
}
Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
<< var << Init->getSourceRange();
- for (unsigned I = 0, N = Notes.size(); I != N; ++I)
- Diag(Notes[I].first, Notes[I].second);
- } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) {
- auto *Attr = var->getAttr<ConstInitAttr>();
- Diag(var->getLocation(), diag::err_require_constant_init_failed)
+ for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+ Diag(Notes[I].first, Notes[I].second);
+ }
+ } else if (var->mightBeUsableInConstantExpressions(Context)) {
+ // Check whether the initializer of a const variable of integral or
+ // enumeration type is an ICE now, since we can't tell whether it was
+ // initialized by a constant expression if we check later.
+ var->checkInitIsICE();
+ }
+
+ // Don't emit further diagnostics about constexpr globals since they
+ // were just diagnosed.
+ if (!var->isConstexpr() && GlobalStorage && var->hasAttr<ConstInitAttr>()) {
+ // FIXME: Need strict checking in C++03 here.
+ bool DiagErr = getLangOpts().CPlusPlus11
+ ? !var->checkInitIsICE() : !checkConstInit();
+ if (DiagErr) {
+ auto *Attr = var->getAttr<ConstInitAttr>();
+ Diag(var->getLocation(), diag::err_require_constant_init_failed)
<< Init->getSourceRange();
- Diag(Attr->getLocation(), diag::note_declared_required_constant_init_here)
- << Attr->getRange() << Attr->isConstinit();
- for (auto &it : Notes)
- Diag(it.first, it.second);
- } else if (IsGlobal &&
- !getDiagnostics().isIgnored(diag::warn_global_constructor,
- var->getLocation())) {
+ Diag(Attr->getLocation(),
+ diag::note_declared_required_constant_init_here)
+ << Attr->getRange() << Attr->isConstinit();
+ if (getLangOpts().CPlusPlus11) {
+ APValue Value;
+ SmallVector<PartialDiagnosticAt, 8> Notes;
+ Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes);
+ for (auto &it : Notes)
+ Diag(it.first, it.second);
+ } else {
+ Diag(CacheCulprit->getExprLoc(),
+ diag::note_invalid_subexpr_in_const_expr)
+ << CacheCulprit->getSourceRange();
+ }
+ }
+ }
+ else if (!var->isConstexpr() && IsGlobal &&
+ !getDiagnostics().isIgnored(diag::warn_global_constructor,
+ var->getLocation())) {
// Warn about globals which don't have a constant initializer. Don't
// warn about globals with a non-trivial destructor because we already
// warned about them.
CXXRecordDecl *RD = baseType->getAsCXXRecordDecl();
if (!(RD && !RD->hasTrivialDestructor())) {
- // checkConstInit() here permits trivial default initialization even in
- // C++11 onwards, where such an initializer is not a constant initializer
- // but nonetheless doesn't require a global constructor.
if (!checkConstInit())
Diag(var->getLocation(), diag::warn_global_constructor)
- << Init->getSourceRange();
+ << Init->getSourceRange();
}
}
}
// Require the destructor.
- if (!type->isDependentType())
- if (const RecordType *recordType = baseType->getAs<RecordType>())
- FinalizeVarWithDestructor(var, recordType);
+ if (const RecordType *recordType = baseType->getAs<RecordType>())
+ FinalizeVarWithDestructor(var, recordType);
// If this variable must be emitted, add it as an initializer for the current
// module.
if (Context.DeclMustBeEmitted(var) && !ModuleScopes.empty())
Context.addModuleInitializer(ModuleScopes.back().Module, var);
-
- // Build the bindings if this is a structured binding declaration.
- if (auto *DD = dyn_cast<DecompositionDecl>(var))
- CheckCompleteDecompositionDeclaration(DD);
}
/// Determines if a variable's alignment is dependent.
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index bc119725e4a0..322de7c87b5f 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1250,7 +1250,8 @@ static bool checkTupleLikeDecomposition(Sema &S,
if (E.isInvalid())
return true;
RefVD->setInit(E.get());
- S.CheckCompleteVariableDeclaration(RefVD);
+ if (!E.get()->isValueDependent())
+ RefVD->checkInitIsICE();
E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
DeclarationNameInfo(B->getDeclName(), Loc),
@@ -11124,8 +11125,8 @@ QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
// Attempt to diagnose reasons why the STL definition of this type
// might be foobar, including it failing to be a constant expression.
// TODO Handle more ways the lookup or result can be invalid.
- if (!VD->isStaticDataMember() ||
- !VD->isUsableInConstantExpressions(Context))
+ if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
+ VD->isWeak() || !VD->checkInitIsICE())
return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
// Attempt to evaluate the var decl as a constant expression and extract
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 797232885687..60930e71aa01 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -4453,7 +4453,7 @@ void ASTDeclReader::UpdateDecl(Decl *D,
uint64_t Val = Record.readInt();
if (Val && !VD->getInit()) {
VD->setInit(Record.readExpr());
- if (Val != 1) {
+ if (Val > 1) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3
EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
Eval->HasConstantInitialization = (Val & 2) != 0;
Eval->HasConstantDestruction = (Val & 4) != 0;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index f0ce843bd3e4..bf3f92a2b3cc 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4980,7 +4980,13 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
const VarDecl *VD = cast<VarDecl>(D);
Record.push_back(VD->isInline());
Record.push_back(VD->isInlineSpecified());
- Record.AddVarDeclInit(VD);
+ if (VD->getInit()) {
+ Record.push_back(!VD->isInitKnownICE() ? 1
+ : (VD->isInitICE() ? 3 : 2));
+ Record.AddStmt(const_cast<Expr*>(VD->getInit()));
+ } else {
+ Record.push_back(0);
+ }
break;
}
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 47ed44898f49..be53f58afd6e 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1006,7 +1006,19 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
}
Record.push_back(D->getLinkageInternal());
- Record.AddVarDeclInit(D);
+ if (D->getInit()) {
+ if (!D->isInitKnownICE())
+ Record.push_back(1);
+ else {
+ Record.push_back(
+ 2 |
+ (D->isInitICE() ? 1 : 0) |
+ (D->ensureEvaluatedStmt()->HasConstantDestruction ? 4 : 0));
+ }
+ Record.AddStmt(D->getInit());
+ } else {
+ Record.push_back(0);
+ }
if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) {
BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D);
diff --git a/clang/test/CodeGen/enable_if.c b/clang/test/CodeGen/enable_if.c
index 1d830ae68f54..5e9f904fdd3f 100644
--- a/clang/test/CodeGen/enable_if.c
+++ b/clang/test/CodeGen/enable_if.c
@@ -65,19 +65,19 @@ void test3() {
}
-enum { TRUEFACTS = 1 };
+const int TRUEFACTS = 1;
void qux(int m) __attribute__((overloadable, enable_if(1, ""),
enable_if(TRUEFACTS, "")));
void qux(int m) __attribute__((overloadable, enable_if(1, "")));
// CHECK-LABEL: define void @test4
void test4() {
- // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
+ // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
void (*p)(int) = qux;
- // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
+ // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
void (*p2)(int) = &qux;
- // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
+ // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
p = qux;
- // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
+ // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
p = &qux;
}
diff --git a/clang/test/OpenMP/threadprivate_codegen.cpp b/clang/test/OpenMP/threadprivate_codegen.cpp
index 2ef6522760ab..a46bb6907015 100644
--- a/clang/test/OpenMP/threadprivate_codegen.cpp
+++ b/clang/test/OpenMP/threadprivate_codegen.cpp
@@ -598,8 +598,8 @@ int main() {
// CHECK-DEBUG-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// CHECK-DEBUG-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[ST_INT_ST_VAL]]
// CHECK-DEBUG-NEXT: store [[INT]] [[ADD]], [[INT]]* [[RES:.+]]
- //
- // CHECK-TLS: [[ST_INT_ST_VAL:%.*]] = load i32, i32* [[ST_INT_ST_ADDR:[^,]+]]
+ // CHECK-TLS: [[ST_INT_ST_ADDR:%.*]] = call i32* [[ST_INT_ST_TLS_INITD:[^,]+]]
+ // CHECK-TLS-NEXT: [[ST_INT_ST_VAL:%.*]] = load i32, i32* [[ST_INT_ST_ADDR]]
// CHECK-TLS-NEXT: [[RES:%.*]] = load i32, i32* [[RES_ADDR]]
// CHECK-TLS-NEXT: [[ADD:%.*]] = add {{.*}} i32 [[RES]], [[ST_INT_ST_VAL]]
// CHECK-TLS-NEXT: store i32 [[ADD]], i32* [[RES_ADDR]]
@@ -620,8 +620,8 @@ int main() {
// CHECK-DEBUG-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// CHECK-DEBUG-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[FLOAT_TO_INT_CONV]]
// CHECK-DEBUG-NEXT: store [[INT]] [[ADD]], [[INT]]* [[RES:.+]]
- //
- // CHECK-TLS: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR:[^,]+]]
+ // CHECK-TLS: [[ST_FLOAT_ST_ADDR:%.*]] = call float* [[ST_FLOAT_ST_TLS_INITD:[^,]+]]
+ // CHECK-TLS-NEXT: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR]]
// CHECK-TLS-NEXT: [[FLOAT_TO_INT_CONV:%.*]] = fptosi float [[ST_FLOAT_ST_VAL]] to i32
// CHECK-TLS-NEXT: [[RES:%.*]] = load i32, i32* [[RES_ADDR]]
// CHECK-TLS-NEXT: [[ADD:%.*]] = add {{.*}} i32 [[RES]], [[FLOAT_TO_INT_CONV]]
@@ -727,14 +727,14 @@ int main() {
// CHECK-TLS: call void [[ARR_X_TLS_INIT]]
// CHECK-TLS: ret [2 x [3 x [[S1]]]]* [[ARR_X]]
// CHECK-TLS: }
-//
-//
-//
-//
-//
-//
-//
-//
+// CHECK-TLS: define {{.*}} i32* [[ST_INT_ST_TLS_INITD]] {{#[0-9]+}} comdat {
+// CHECK-TLS-NOT: call
+// CHECK-TLS: ret i32* [[ST_INT_ST]]
+// CHECK-TLS: }
+// CHECK-TLS: define {{.*}} float* [[ST_FLOAT_ST_TLS_INITD]] {{#[0-9]+}} comdat {
+// CHECK-TLS-NOT: call
+// CHECK-TLS: ret float* [[ST_FLOAT_ST]]
+// CHECK-TLS: }
// CHECK-TLS: define {{.*}} [[S4]]* [[ST_S4_ST_TLS_INITD]] {{#[0-9]+}} comdat {
// CHECK-TLS: call void [[ST_S4_ST_TLS_INIT]]
// CHECK-TLS: ret [[S4]]* [[ST_S4_ST]]
@@ -874,8 +874,8 @@ int foobar() {
// CHECK-DEBUG-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// CHECK-DEBUG-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[ST_INT_ST_VAL]]
// CHECK-DEBUG-NEXT: store [[INT]] [[ADD]], [[INT]]* [[RES:.+]]
- //
- // OMP45-TLS: [[ST_INT_ST_VAL:%.*]] = load [[INT]], [[INT]]* [[ST_INT_ST_ADDR:[^,]+]]
+ // OMP45-TLS: [[ST_INT_ST_ADDR:%.*]] = call i32* [[ST_INT_ST_TLS_INITD]]
+ // OMP45-TLS-NEXT: [[ST_INT_ST_VAL:%.*]] = load [[INT]], [[INT]]* [[ST_INT_ST_ADDR]]
// OMP45-TLS-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// OMP45-TLS-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[ST_INT_ST_VAL]]
// OMP45-TLS-NEXT: store [[INT]] [[ADD]], [[INT]]* [[RES:.+]]
@@ -896,8 +896,8 @@ int foobar() {
// CHECK-DEBUG-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// CHECK-DEBUG-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[FLOAT_TO_INT_CONV]]
// CHECK-DEBUG-NEXT: store [[INT]] [[ADD]], [[INT]]* [[RES:.+]]
- //
- // OMP45-TLS: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR:[^,]+]]
+ // OMP45-TLS: [[ST_FLOAT_ST_ADDR:%.*]] = call float* [[ST_FLOAT_ST_TLS_INITD]]
+ // OMP45-TLS-NEXT: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR]]
// OMP45-TLS-NEXT: [[FLOAT_TO_INT_CONV:%.*]] = fptosi float [[ST_FLOAT_ST_VAL]] to [[INT]]
// OMP45-TLS-NEXT: [[RES:%.*]] = load [[INT]], [[INT]]* [[RES_ADDR]]
// OMP45-TLS-NEXT: [[ADD:%.*]] = add {{.*}} [[INT]] [[RES]], [[FLOAT_TO_INT_CONV]]
diff --git a/clang/test/Sema/enable_if.c b/clang/test/Sema/enable_if.c
index d96a53d94e1e..b4bb2ecd0d20 100644
--- a/clang/test/Sema/enable_if.c
+++ b/clang/test/Sema/enable_if.c
@@ -5,7 +5,7 @@
typedef int mode_t;
typedef unsigned long size_t;
-enum { TRUE = 1 };
+const int TRUE = 1;
int open(const char *pathname, int flags) __attribute__((enable_if(!(flags & O_CREAT), "must specify mode when using O_CREAT"))) __attribute__((overloadable)); // expected-note{{candidate disabled: must specify mode when using O_CREAT}}
int open(const char *pathname, int flags, mode_t mode) __attribute__((overloadable)); // expected-note{{candidate function not viable: requires 3 arguments, but 2 were provided}}
@@ -114,7 +114,7 @@ void f(int n) __attribute__((enable_if(unresolvedid, "chosen when 'unresolvedid'
int global;
void f(int n) __attribute__((enable_if(global == 0, "chosen when 'global' is zero"))); // expected-error{{'enable_if' attribute expression never produces a constant expression}} // expected-note{{subexpression not valid in a constant expression}}
-enum { cst = 7 };
+const int cst = 7;
void return_cst(void) __attribute__((overloadable)) __attribute__((enable_if(cst == 7, "chosen when 'cst' is 7")));
void test_return_cst() { return_cst(); }
diff --git a/clang/test/SemaCXX/constant-expression.cpp b/clang/test/SemaCXX/constant-expression.cpp
index a5e571a97eb2..2bec62f46b66 100644
--- a/clang/test/SemaCXX/constant-expression.cpp
+++ b/clang/test/SemaCXX/constant-expression.cpp
@@ -98,9 +98,9 @@ void diags(int n) {
namespace IntOrEnum {
const int k = 0;
- const int &p = k; // expected-note {{declared here}}
+ const int &p = k;
template<int n> struct S {};
- S<p> s; // expected-error {{not an integral constant expression}} expected-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}}
+ S<p> s; // expected-error {{not an integral constant expression}}
}
extern const int recurse1;
diff --git a/clang/test/SemaCXX/i-c-e-cxx.cpp b/clang/test/SemaCXX/i-c-e-cxx.cpp
index da9be1229a54..a09ff5ac8d9f 100644
--- a/clang/test/SemaCXX/i-c-e-cxx.cpp
+++ b/clang/test/SemaCXX/i-c-e-cxx.cpp
@@ -19,6 +19,9 @@ void f() {
int a() {
const int t=t; // expected-note {{declared here}}
+#if __cplusplus <= 199711L
+ // expected-note at -2 {{read of object outside its lifetime}}
+#endif
switch(1) { // do not warn that 1 is not a case value;
// 't' might have been expected to evalaute to 1
More information about the cfe-commits
mailing list