forked from OSchip/llvm-project
Revert "Revert "Ensure that checkInitIsICE is called exactly once for every variable""
This reverts commit a2ac64dd90
.
This commit is contained in:
parent
a2ac64dd90
commit
e56e7bd469
|
@ -835,9 +835,14 @@ 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.
|
||||
|
@ -1257,14 +1262,15 @@ public:
|
|||
/// 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(ASTContext &C) const;
|
||||
bool mightBeUsableInConstantExpressions(const 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(ASTContext &C) const;
|
||||
bool isUsableInConstantExpressions(const 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.
|
||||
|
|
|
@ -266,6 +266,9 @@ public:
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ clang::getComparisonCategoryForBuiltinCmp(QualType T) {
|
|||
|
||||
bool ComparisonCategoryInfo::ValueInfo::hasValidIntValue() const {
|
||||
assert(VD && "must have var decl");
|
||||
if (!VD->checkInitIsICE())
|
||||
if (!VD->isUsableInConstantExpressions(VD->getASTContext()))
|
||||
return false;
|
||||
|
||||
// Before we attempt to get the value of the first field, ensure that we
|
||||
|
|
|
@ -2277,7 +2277,7 @@ void VarDecl::setInit(Expr *I) {
|
|||
Init = I;
|
||||
}
|
||||
|
||||
bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const {
|
||||
bool VarDecl::mightBeUsableInConstantExpressions(const 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(ASTContext &C) const {
|
|||
return Lang.CPlusPlus11 && isConstexpr();
|
||||
}
|
||||
|
||||
bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const {
|
||||
bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
|
||||
// C++2a [expr.const]p3:
|
||||
// A variable is usable in constant expressions after its initializing
|
||||
// declaration is encountered...
|
||||
|
@ -2356,6 +2356,10 @@ 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());
|
||||
|
@ -2365,19 +2369,17 @@ 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;
|
||||
}
|
||||
|
||||
|
@ -2405,18 +2407,11 @@ 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 = Init.dyn_cast<EvaluatedStmt *>())
|
||||
if (EvaluatedStmt *Eval = getEvaluatedStmt())
|
||||
if (Eval->WasEvaluated)
|
||||
return &Eval->Evaluated;
|
||||
|
||||
|
@ -2622,7 +2617,7 @@ bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
|
|||
|
||||
QualType::DestructionKind
|
||||
VarDecl::needsDestruction(const ASTContext &Ctx) const {
|
||||
if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
|
||||
if (EvaluatedStmt *Eval = getEvaluatedStmt())
|
||||
if (Eval->HasConstantDestruction)
|
||||
return QualType::DK_none;
|
||||
|
||||
|
|
|
@ -3362,7 +3362,6 @@ 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
|
||||
|
@ -3377,11 +3376,6 @@ 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,
|
||||
|
@ -8193,6 +8187,12 @@ 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;
|
||||
|
|
|
@ -361,8 +361,9 @@ public:
|
|||
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
|
||||
// ICE-ness not varying between translation units, which isn't actually
|
||||
// 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
|
||||
// guaranteed by the standard but is necessary for sanity.
|
||||
return InitDecl->hasConstantInitialization();
|
||||
}
|
||||
|
|
|
@ -12958,18 +12958,14 @@ 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);
|
||||
|
@ -13024,65 +13020,47 @@ 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 (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)
|
||||
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)
|
||||
<< Init->getSourceRange();
|
||||
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())) {
|
||||
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())) {
|
||||
// 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 (const RecordType *recordType = baseType->getAs<RecordType>())
|
||||
FinalizeVarWithDestructor(var, recordType);
|
||||
if (!type->isDependentType())
|
||||
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.
|
||||
|
|
|
@ -1250,8 +1250,7 @@ static bool checkTupleLikeDecomposition(Sema &S,
|
|||
if (E.isInvalid())
|
||||
return true;
|
||||
RefVD->setInit(E.get());
|
||||
if (!E.get()->isValueDependent())
|
||||
RefVD->checkInitIsICE();
|
||||
S.CheckCompleteVariableDeclaration(RefVD);
|
||||
|
||||
E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
|
||||
DeclarationNameInfo(B->getDeclName(), Loc),
|
||||
|
@ -11125,8 +11124,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->isConstexpr() || !VD->hasInit() ||
|
||||
VD->isWeak() || !VD->checkInitIsICE())
|
||||
if (!VD->isStaticDataMember() ||
|
||||
!VD->isUsableInConstantExpressions(Context))
|
||||
return UnsupportedSTLError(USS_InvalidMember, MemName, VD);
|
||||
|
||||
// Attempt to evaluate the var decl as a constant expression and extract
|
||||
|
|
|
@ -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) { // IsInitKnownICE = 1, IsInitNotICE = 2, IsInitICE = 3
|
||||
if (Val != 1) {
|
||||
EvaluatedStmt *Eval = VD->ensureEvaluatedStmt();
|
||||
Eval->HasConstantInitialization = (Val & 2) != 0;
|
||||
Eval->HasConstantDestruction = (Val & 4) != 0;
|
||||
|
|
|
@ -4980,13 +4980,7 @@ void ASTWriter::WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord) {
|
|||
const VarDecl *VD = cast<VarDecl>(D);
|
||||
Record.push_back(VD->isInline());
|
||||
Record.push_back(VD->isInlineSpecified());
|
||||
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);
|
||||
}
|
||||
Record.AddVarDeclInit(VD);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1006,19 +1006,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
|
|||
}
|
||||
Record.push_back(D->getLinkageInternal());
|
||||
|
||||
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);
|
||||
}
|
||||
Record.AddVarDeclInit(D);
|
||||
|
||||
if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) {
|
||||
BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D);
|
||||
|
|
|
@ -65,19 +65,19 @@ void test3() {
|
|||
}
|
||||
|
||||
|
||||
const int TRUEFACTS = 1;
|
||||
enum { 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_ifIXLi1EEXL_Z9TRUEFACTSEEEi
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
|
||||
void (*p)(int) = qux;
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
|
||||
void (*p2)(int) = &qux;
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
|
||||
p = qux;
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi
|
||||
// CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi
|
||||
p = &qux;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ADDR:%.*]] = call i32* [[ST_INT_ST_TLS_INITD:[^,]+]]
|
||||
// CHECK-TLS-NEXT: [[ST_INT_ST_VAL:%.*]] = load i32, i32* [[ST_INT_ST_ADDR]]
|
||||
//
|
||||
// CHECK-TLS: [[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_ADDR:%.*]] = call float* [[ST_FLOAT_ST_TLS_INITD:[^,]+]]
|
||||
// CHECK-TLS-NEXT: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR]]
|
||||
//
|
||||
// CHECK-TLS: [[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_ADDR:%.*]] = call i32* [[ST_INT_ST_TLS_INITD]]
|
||||
// OMP45-TLS-NEXT: [[ST_INT_ST_VAL:%.*]] = load [[INT]], [[INT]]* [[ST_INT_ST_ADDR]]
|
||||
//
|
||||
// OMP45-TLS: [[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_ADDR:%.*]] = call float* [[ST_FLOAT_ST_TLS_INITD]]
|
||||
// OMP45-TLS-NEXT: [[ST_FLOAT_ST_VAL:%.*]] = load float, float* [[ST_FLOAT_ST_ADDR]]
|
||||
//
|
||||
// OMP45-TLS: [[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]]
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
typedef int mode_t;
|
||||
typedef unsigned long size_t;
|
||||
|
||||
const int TRUE = 1;
|
||||
enum { 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}}
|
||||
|
||||
const int cst = 7;
|
||||
enum { cst = 7 };
|
||||
void return_cst(void) __attribute__((overloadable)) __attribute__((enable_if(cst == 7, "chosen when 'cst' is 7")));
|
||||
void test_return_cst() { return_cst(); }
|
||||
|
||||
|
|
|
@ -98,9 +98,9 @@ void diags(int n) {
|
|||
|
||||
namespace IntOrEnum {
|
||||
const int k = 0;
|
||||
const int &p = k;
|
||||
const int &p = k; // expected-note {{declared here}}
|
||||
template<int n> struct S {};
|
||||
S<p> s; // expected-error {{not an integral constant expression}}
|
||||
S<p> s; // expected-error {{not an integral constant expression}} expected-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}}
|
||||
}
|
||||
|
||||
extern const int recurse1;
|
||||
|
|
|
@ -19,9 +19,6 @@ void f() {
|
|||
|
||||
int a() {
|
||||
const int t=t; // expected-note {{declared here}}
|
||||
#if __cplusplus <= 199711L
|
||||
// expected-note@-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
|
||||
|
|
Loading…
Reference in New Issue