forked from OSchip/llvm-project
Fix a couple issues where we didn't correctly delay diagnostics in PotentiallyPotentiallyEvaluated contexts. In preparation for making sizeof() PotentiallyPotentiallyEvaluated.
llvm-svn: 148367
This commit is contained in:
parent
adcc938c46
commit
fbc0dff6f8
|
@ -165,6 +165,7 @@ namespace sema {
|
|||
class DelayedDiagnostic;
|
||||
class FunctionScopeInfo;
|
||||
class LambdaScopeInfo;
|
||||
class PossiblyUnreachableDiag;
|
||||
class TemplateDeductionInfo;
|
||||
}
|
||||
|
||||
|
@ -519,6 +520,12 @@ public:
|
|||
typedef SmallVector<std::pair<SourceLocation, PartialDiagnostic>, 10>
|
||||
PotentiallyEmittedDiagnostics;
|
||||
|
||||
typedef SmallVector<sema::DelayedDiagnostic, 10>
|
||||
PotentiallyEmittedDelayedDiag;
|
||||
|
||||
typedef SmallVector<sema::PossiblyUnreachableDiag, 10>
|
||||
PotentiallyEmittedPossiblyUnreachableDiag;
|
||||
|
||||
/// \brief Describes how the expressions currently being parsed are
|
||||
/// evaluated at run-time, if at all.
|
||||
enum ExpressionEvaluationContext {
|
||||
|
@ -579,16 +586,20 @@ public:
|
|||
/// evaluated.
|
||||
PotentiallyReferencedDecls *PotentiallyReferenced;
|
||||
|
||||
/// \brief The set of diagnostics to emit should this potentially
|
||||
/// potentially-evaluated context become evaluated.
|
||||
PotentiallyEmittedDiagnostics *PotentiallyDiagnosed;
|
||||
// There are three kinds of diagnostics we care about in
|
||||
// PotentiallyPotentiallyEvaluated contexts: regular Diag diagnostics,
|
||||
// DelayedDiagnostics, and DiagRuntimeBehavior diagnostics.
|
||||
PotentiallyEmittedDiagnostics *SavedDiag;
|
||||
PotentiallyEmittedDelayedDiag *SavedDelayedDiag;
|
||||
PotentiallyEmittedPossiblyUnreachableDiag *SavedRuntimeDiag;
|
||||
|
||||
ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context,
|
||||
unsigned NumCleanupObjects,
|
||||
bool ParentNeedsCleanups)
|
||||
: Context(Context), ParentNeedsCleanups(ParentNeedsCleanups),
|
||||
NumCleanupObjects(NumCleanupObjects),
|
||||
PotentiallyReferenced(0), PotentiallyDiagnosed(0) { }
|
||||
PotentiallyReferenced(0), SavedDiag(0), SavedDelayedDiag(0),
|
||||
SavedRuntimeDiag(0) { }
|
||||
|
||||
void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
|
||||
if (!PotentiallyReferenced)
|
||||
|
@ -596,18 +607,13 @@ public:
|
|||
PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
|
||||
}
|
||||
|
||||
void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD) {
|
||||
if (!PotentiallyDiagnosed)
|
||||
PotentiallyDiagnosed = new PotentiallyEmittedDiagnostics;
|
||||
PotentiallyDiagnosed->push_back(std::make_pair(Loc, PD));
|
||||
}
|
||||
void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD);
|
||||
|
||||
void Destroy() {
|
||||
delete PotentiallyReferenced;
|
||||
delete PotentiallyDiagnosed;
|
||||
PotentiallyReferenced = 0;
|
||||
PotentiallyDiagnosed = 0;
|
||||
}
|
||||
void addRuntimeDiagnostic(const sema::PossiblyUnreachableDiag &PUD);
|
||||
|
||||
void addDelayedDiagnostic(const sema::DelayedDiagnostic &DD);
|
||||
|
||||
void Destroy();
|
||||
};
|
||||
|
||||
/// A stack of expression evaluation contexts.
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Sema/SemaInternal.h"
|
||||
#include "clang/Sema/DelayedDiagnostic.h"
|
||||
#include "clang/Sema/Initialization.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/ScopeInfo.h"
|
||||
#include "clang/Sema/AnalysisBasedWarnings.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/ASTMutationListener.h"
|
||||
|
@ -9360,6 +9362,39 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result,
|
|||
return false;
|
||||
}
|
||||
|
||||
void Sema::ExpressionEvaluationContextRecord::Destroy() {
|
||||
delete PotentiallyReferenced;
|
||||
delete SavedDiag;
|
||||
delete SavedRuntimeDiag;
|
||||
delete SavedDelayedDiag;
|
||||
PotentiallyReferenced = 0;
|
||||
SavedDiag = 0;
|
||||
SavedRuntimeDiag = 0;
|
||||
SavedDelayedDiag = 0;
|
||||
}
|
||||
|
||||
void Sema::ExpressionEvaluationContextRecord::addDiagnostic(
|
||||
SourceLocation Loc, const PartialDiagnostic &PD) {
|
||||
if (!SavedDiag)
|
||||
SavedDiag = new PotentiallyEmittedDiagnostics;
|
||||
SavedDiag->push_back(std::make_pair(Loc, PD));
|
||||
}
|
||||
|
||||
void Sema::ExpressionEvaluationContextRecord::addRuntimeDiagnostic(
|
||||
const sema::PossiblyUnreachableDiag &PUD) {
|
||||
if (!SavedRuntimeDiag)
|
||||
SavedRuntimeDiag = new PotentiallyEmittedPossiblyUnreachableDiag;
|
||||
SavedRuntimeDiag->push_back(PUD);
|
||||
}
|
||||
|
||||
void Sema::ExpressionEvaluationContextRecord::addDelayedDiagnostic(
|
||||
const sema::DelayedDiagnostic &DD) {
|
||||
if (!SavedDelayedDiag)
|
||||
SavedDelayedDiag = new PotentiallyEmittedDelayedDiag;
|
||||
SavedDelayedDiag->push_back(DD);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
|
||||
ExprEvalContexts.push_back(
|
||||
|
@ -9386,14 +9421,32 @@ void Sema::PopExpressionEvaluationContext() {
|
|||
MarkDeclarationReferenced(I->first, I->second);
|
||||
}
|
||||
|
||||
if (Rec.PotentiallyDiagnosed) {
|
||||
if (Rec.SavedDiag) {
|
||||
// Emit any pending diagnostics.
|
||||
for (PotentiallyEmittedDiagnostics::iterator
|
||||
I = Rec.PotentiallyDiagnosed->begin(),
|
||||
IEnd = Rec.PotentiallyDiagnosed->end();
|
||||
I = Rec.SavedDiag->begin(),
|
||||
IEnd = Rec.SavedDiag->end();
|
||||
I != IEnd; ++I)
|
||||
Diag(I->first, I->second);
|
||||
}
|
||||
|
||||
if (Rec.SavedDelayedDiag) {
|
||||
// Emit any pending delayed diagnostics.
|
||||
for (PotentiallyEmittedDelayedDiag::iterator
|
||||
I = Rec.SavedDelayedDiag->begin(),
|
||||
IEnd = Rec.SavedDelayedDiag->end();
|
||||
I != IEnd; ++I)
|
||||
DelayedDiagnostics.add(*I);
|
||||
}
|
||||
|
||||
if (Rec.SavedRuntimeDiag) {
|
||||
// Emit any pending runtime diagnostics.
|
||||
for (PotentiallyEmittedPossiblyUnreachableDiag::iterator
|
||||
I = Rec.SavedRuntimeDiag->begin(),
|
||||
IEnd = Rec.SavedRuntimeDiag->end();
|
||||
I != IEnd; ++I)
|
||||
FunctionScopes.back()->PossiblyUnreachableDiags.push_back(*I);
|
||||
}
|
||||
}
|
||||
|
||||
// When are coming out of an unevaluated context, clear out any
|
||||
|
@ -9759,7 +9812,8 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
|
|||
return true;
|
||||
|
||||
case PotentiallyPotentiallyEvaluated:
|
||||
ExprEvalContexts.back().addDiagnostic(Loc, PD);
|
||||
ExprEvalContexts.back().addRuntimeDiagnostic(
|
||||
sema::PossiblyUnreachableDiag(PD, Loc, Statement));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1057,23 +1057,40 @@ static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
|
|||
} else if (type->isObjCARCImplicitlyUnretainedType()) {
|
||||
implicitLifetime = Qualifiers::OCL_ExplicitNone;
|
||||
|
||||
// If we are in an unevaluated context, like sizeof, assume ExplicitNone and
|
||||
// If we are in an unevaluated context, like sizeof, assume Autoreleasing and
|
||||
// don't give error.
|
||||
} else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated ||
|
||||
S.ExprEvalContexts.back().Context == Sema::ConstantEvaluated) {
|
||||
implicitLifetime = Qualifiers::OCL_ExplicitNone;
|
||||
implicitLifetime = Qualifiers::OCL_Autoreleasing;
|
||||
|
||||
// If that failed, give an error and recover using __autoreleasing.
|
||||
} else {
|
||||
// These types can show up in private ivars in system headers, so
|
||||
// we need this to not be an error in those cases. Instead we
|
||||
// want to delay.
|
||||
//
|
||||
// Also, make sure we delay appropriately in
|
||||
// PotentiallyPotentiallyEvaluated contexts.
|
||||
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
|
||||
S.DelayedDiagnostics.add(
|
||||
sema::DelayedDiagnostic::makeForbiddenType(loc,
|
||||
diag::err_arc_indirect_no_ownership, type, isReference));
|
||||
if (S.ExprEvalContexts.back().Context ==
|
||||
Sema::PotentiallyPotentiallyEvaluated) {
|
||||
S.ExprEvalContexts.back().addDelayedDiagnostic(
|
||||
sema::DelayedDiagnostic::makeForbiddenType(loc,
|
||||
diag::err_arc_indirect_no_ownership, type, isReference));
|
||||
} else {
|
||||
S.DelayedDiagnostics.add(
|
||||
sema::DelayedDiagnostic::makeForbiddenType(loc,
|
||||
diag::err_arc_indirect_no_ownership, type, isReference));
|
||||
}
|
||||
} else {
|
||||
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
|
||||
if (S.ExprEvalContexts.back().Context ==
|
||||
Sema::PotentiallyPotentiallyEvaluated) {
|
||||
S.ExprEvalContexts.back().addDiagnostic(loc,
|
||||
S.PDiag(diag::err_arc_indirect_no_ownership)
|
||||
<< type << isReference);
|
||||
} else {
|
||||
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
|
||||
}
|
||||
}
|
||||
implicitLifetime = Qualifiers::OCL_Autoreleasing;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
// Make sure diagnostics that we don't print based on runtime control
|
||||
// flow are delayed correctly in cases where we can't immediately tell whether
|
||||
// the context is unevaluated.
|
||||
|
||||
namespace std {
|
||||
class type_info;
|
||||
}
|
||||
|
||||
int& NP(int);
|
||||
void test1() { (void)typeid(NP(1 << 32)); }
|
||||
|
||||
class Poly { virtual ~Poly(); };
|
||||
Poly& P(int);
|
||||
void test2() { (void)typeid(P(1 << 32)); } // expected-warning {{shift count >= width of type}}
|
||||
|
||||
void test3() { 1 ? (void)0 : (void)typeid(P(1 << 32)); }
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -fobjc-arc %s
|
||||
|
||||
// Make sure the ARC auto-deduction of id* in unevaluated contexts
|
||||
// works correctly in cases where we can't immediately tell whether the
|
||||
// context is unevaluated.
|
||||
|
||||
namespace std {
|
||||
class type_info;
|
||||
}
|
||||
|
||||
int& NP(void*);
|
||||
void test1() { (void)typeid(NP((void*)(id*)0)); }
|
||||
|
||||
class Poly { virtual ~Poly(); };
|
||||
Poly& P(void*);
|
||||
void test2() { (void)typeid(P((void*)(id*)0)); } // expected-error {{pointer to non-const type 'id'}}
|
Loading…
Reference in New Issue