Remove PotentiallyPotentiallyEvaluated, and replace it with a much simpler and less error-prone way of handling the relevant cases. Towards marking of whether a declaration is used more accurately.
llvm-svn: 148522
This commit is contained in:
parent
6561d15dcb
commit
456f01833b
|
@ -511,21 +511,6 @@ public:
|
|||
/// call was found yet.
|
||||
bool ObjCShouldCallSuperFinalize;
|
||||
|
||||
/// \brief The set of declarations that have been referenced within
|
||||
/// a potentially evaluated expression.
|
||||
typedef SmallVector<std::pair<SourceLocation, Decl *>, 10>
|
||||
PotentiallyReferencedDecls;
|
||||
|
||||
/// \brief A set of diagnostics that may be emitted.
|
||||
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 {
|
||||
|
@ -546,13 +531,6 @@ public:
|
|||
/// expression at run time.
|
||||
PotentiallyEvaluated,
|
||||
|
||||
/// \brief The current expression may be potentially evaluated or it may
|
||||
/// be unevaluated, but it is impossible to tell from the lexical context.
|
||||
/// This evaluation context is used primary for the operand of the C++
|
||||
/// \c typeid expression, whose argument is potentially evaluated only when
|
||||
/// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
|
||||
PotentiallyPotentiallyEvaluated,
|
||||
|
||||
/// \brief The current expression is potentially evaluated, but any
|
||||
/// declarations referenced inside that expression are only used if
|
||||
/// in fact the current expression is used.
|
||||
|
@ -577,43 +555,11 @@ public:
|
|||
/// this expression evaluation context.
|
||||
unsigned NumCleanupObjects;
|
||||
|
||||
/// \brief The set of declarations referenced within a
|
||||
/// potentially potentially-evaluated context.
|
||||
///
|
||||
/// When leaving a potentially potentially-evaluated context, each
|
||||
/// of these elements will be as referenced if the corresponding
|
||||
/// potentially potentially evaluated expression is potentially
|
||||
/// evaluated.
|
||||
PotentiallyReferencedDecls *PotentiallyReferenced;
|
||||
|
||||
// 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), SavedDiag(0), SavedDelayedDiag(0),
|
||||
SavedRuntimeDiag(0) { }
|
||||
|
||||
void addReferencedDecl(SourceLocation Loc, Decl *Decl) {
|
||||
if (!PotentiallyReferenced)
|
||||
PotentiallyReferenced = new PotentiallyReferencedDecls;
|
||||
PotentiallyReferenced->push_back(std::make_pair(Loc, Decl));
|
||||
}
|
||||
|
||||
void addDiagnostic(SourceLocation Loc, const PartialDiagnostic &PD);
|
||||
|
||||
void addRuntimeDiagnostic(const sema::PossiblyUnreachableDiag &PUD);
|
||||
|
||||
void addDelayedDiagnostic(const sema::DelayedDiagnostic &DD);
|
||||
|
||||
void Destroy();
|
||||
NumCleanupObjects(NumCleanupObjects) { }
|
||||
};
|
||||
|
||||
/// A stack of expression evaluation contexts.
|
||||
|
@ -2309,6 +2255,8 @@ public:
|
|||
|
||||
void DiscardCleanupsInEvaluationContext();
|
||||
|
||||
ExprResult TranformToPotentiallyEvaluated(Expr *E);
|
||||
|
||||
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
|
||||
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
|
||||
void MarkDeclarationsReferencedInExpr(Expr *E);
|
||||
|
@ -3116,8 +3064,7 @@ public:
|
|||
QualType getCurrentThisType();
|
||||
|
||||
/// \brief Make sure the value of 'this' is actually available in the current
|
||||
/// context, if it is a potentially evaluated context. This check can be
|
||||
/// delayed in PotentiallyPotentiallyEvaluated contexts.
|
||||
/// context, if it is a potentially evaluated context.
|
||||
void CheckCXXThisCapture(SourceLocation Loc);
|
||||
|
||||
/// ActOnCXXBoolLiteral - Parse {true,false} literals.
|
||||
|
|
|
@ -924,10 +924,10 @@ ExprResult Parser::ParseCXXTypeid() {
|
|||
// operand (Clause 5).
|
||||
//
|
||||
// Note that we can't tell whether the expression is an lvalue of a
|
||||
// polymorphic class type until after we've parsed the expression, so
|
||||
// we the expression is potentially potentially evaluated.
|
||||
EnterExpressionEvaluationContext Unevaluated(Actions,
|
||||
Sema::PotentiallyPotentiallyEvaluated);
|
||||
// polymorphic class type until after we've parsed the expression; we
|
||||
// speculatively assume the subexpression is unevaluated, and fix it up
|
||||
// later.
|
||||
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
|
||||
Result = ParseExpression();
|
||||
|
||||
// Match the ')'.
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/Sema/SemaFixItUtils.h"
|
||||
#include "clang/Sema/Template.h"
|
||||
#include "TreeTransform.h"
|
||||
using namespace clang;
|
||||
using namespace sema;
|
||||
|
||||
|
@ -1208,10 +1209,6 @@ diagnoseUncapturableValueReference(Sema &S, SourceLocation loc,
|
|||
case Sema::PotentiallyEvaluated:
|
||||
case Sema::PotentiallyEvaluatedIfUsed:
|
||||
break;
|
||||
|
||||
case Sema::PotentiallyPotentiallyEvaluated:
|
||||
// FIXME: delay these!
|
||||
break;
|
||||
}
|
||||
|
||||
// Don't diagnose about capture if we're not actually in code right
|
||||
|
@ -9358,39 +9355,54 @@ 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;
|
||||
namespace {
|
||||
// Handle the case where we conclude a expression which we speculatively
|
||||
// considered to be unevaluated is actually evaluated.
|
||||
class TransformToPE : public TreeTransform<TransformToPE> {
|
||||
typedef TreeTransform<TransformToPE> BaseTransform;
|
||||
|
||||
public:
|
||||
TransformToPE(Sema &SemaRef) : BaseTransform(SemaRef) { }
|
||||
|
||||
// Make sure we redo semantic analysis
|
||||
bool AlwaysRebuild() { return true; }
|
||||
|
||||
// We need to special-case DeclRefExprs referring to FieldDecls which
|
||||
// are not part of a member pointer formation; normal TreeTransforming
|
||||
// doesn't catch this case because of the way we represent them in the AST.
|
||||
// FIXME: This is a bit ugly; is it really the best way to handle this
|
||||
// case?
|
||||
//
|
||||
// Error on DeclRefExprs referring to FieldDecls.
|
||||
ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
|
||||
if (isa<FieldDecl>(E->getDecl()) &&
|
||||
SemaRef.ExprEvalContexts.back().Context != Sema::Unevaluated)
|
||||
return SemaRef.Diag(E->getLocation(),
|
||||
diag::err_invalid_non_static_member_use)
|
||||
<< E->getDecl() << E->getSourceRange();
|
||||
|
||||
return BaseTransform::TransformDeclRefExpr(E);
|
||||
}
|
||||
|
||||
// Exception: filter out member pointer formation
|
||||
ExprResult TransformUnaryOperator(UnaryOperator *E) {
|
||||
if (E->getOpcode() == UO_AddrOf && E->getType()->isMemberPointerType())
|
||||
return E;
|
||||
|
||||
return BaseTransform::TransformUnaryOperator(E);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void Sema::ExpressionEvaluationContextRecord::addDiagnostic(
|
||||
SourceLocation Loc, const PartialDiagnostic &PD) {
|
||||
if (!SavedDiag)
|
||||
SavedDiag = new PotentiallyEmittedDiagnostics;
|
||||
SavedDiag->push_back(std::make_pair(Loc, PD));
|
||||
ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) {
|
||||
ExprEvalContexts.back().Context =
|
||||
ExprEvalContexts[ExprEvalContexts.size()-2].Context;
|
||||
if (ExprEvalContexts.back().Context == Unevaluated)
|
||||
return E;
|
||||
return TransformToPE(*this).TransformExpr(E);
|
||||
}
|
||||
|
||||
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(
|
||||
|
@ -9405,46 +9417,6 @@ void Sema::PopExpressionEvaluationContext() {
|
|||
ExpressionEvaluationContextRecord Rec = ExprEvalContexts.back();
|
||||
ExprEvalContexts.pop_back();
|
||||
|
||||
if (Rec.Context == PotentiallyPotentiallyEvaluated) {
|
||||
if (Rec.PotentiallyReferenced) {
|
||||
// Mark any remaining declarations in the current position of the stack
|
||||
// as "referenced". If they were not meant to be referenced, semantic
|
||||
// analysis would have eliminated them (e.g., in ActOnCXXTypeId).
|
||||
for (PotentiallyReferencedDecls::iterator
|
||||
I = Rec.PotentiallyReferenced->begin(),
|
||||
IEnd = Rec.PotentiallyReferenced->end();
|
||||
I != IEnd; ++I)
|
||||
MarkDeclarationReferenced(I->first, I->second);
|
||||
}
|
||||
|
||||
if (Rec.SavedDiag) {
|
||||
// Emit any pending diagnostics.
|
||||
for (PotentiallyEmittedDiagnostics::iterator
|
||||
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
|
||||
// temporaries that we may have created as part of the evaluation of
|
||||
// the expression in that context: they aren't relevant because they
|
||||
|
@ -9458,9 +9430,6 @@ void Sema::PopExpressionEvaluationContext() {
|
|||
} else {
|
||||
ExprNeedsCleanups |= Rec.ParentNeedsCleanups;
|
||||
}
|
||||
|
||||
// Destroy the popped expression evaluation record.
|
||||
Rec.Destroy();
|
||||
}
|
||||
|
||||
void Sema::DiscardCleanupsInEvaluationContext() {
|
||||
|
@ -9516,13 +9485,6 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
|
|||
// "used"; handle this below.
|
||||
break;
|
||||
|
||||
case PotentiallyPotentiallyEvaluated:
|
||||
// We are in an expression that may be potentially evaluated; queue this
|
||||
// declaration reference until we know whether the expression is
|
||||
// potentially evaluated.
|
||||
ExprEvalContexts.back().addReferencedDecl(Loc, D);
|
||||
return;
|
||||
|
||||
case PotentiallyEvaluatedIfUsed:
|
||||
// Referenced declarations will only be used if the construct in the
|
||||
// containing expression is used.
|
||||
|
@ -9806,11 +9768,6 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, const Stmt *Statement,
|
|||
Diag(Loc, PD);
|
||||
|
||||
return true;
|
||||
|
||||
case PotentiallyPotentiallyEvaluated:
|
||||
ExprEvalContexts.back().addRuntimeDiagnostic(
|
||||
sema::PossiblyUnreachableDiag(PD, Loc, Statement));
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -310,7 +310,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
|
|||
SourceLocation TypeidLoc,
|
||||
Expr *E,
|
||||
SourceLocation RParenLoc) {
|
||||
bool isUnevaluatedOperand = true;
|
||||
if (E && !E->isTypeDependent()) {
|
||||
if (E->getType()->isPlaceholderType()) {
|
||||
ExprResult result = CheckPlaceholderExpr(E);
|
||||
|
@ -332,7 +331,11 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
|
|||
// polymorphic class type [...] [the] expression is an unevaluated
|
||||
// operand. [...]
|
||||
if (RecordD->isPolymorphic() && E->Classify(Context).isGLValue()) {
|
||||
isUnevaluatedOperand = false;
|
||||
// The subexpression is potentially evaluated; switch the context
|
||||
// and recheck the subexpression.
|
||||
ExprResult Result = TranformToPotentiallyEvaluated(E);
|
||||
if (Result.isInvalid()) return ExprError();
|
||||
E = Result.take();
|
||||
|
||||
// We require a vtable to query the type at run time.
|
||||
MarkVTableUsed(TypeidLoc, RecordD);
|
||||
|
@ -352,12 +355,6 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
|
|||
}
|
||||
}
|
||||
|
||||
// If this is an unevaluated operand, clear out the set of
|
||||
// declaration references we have been computing and eliminate any
|
||||
// temporaries introduced in its computation.
|
||||
if (isUnevaluatedOperand)
|
||||
ExprEvalContexts.back().Context = Unevaluated;
|
||||
|
||||
return Owned(new (Context) CXXTypeidExpr(TypeInfoType.withConst(),
|
||||
E,
|
||||
SourceRange(TypeidLoc, RParenLoc)));
|
||||
|
@ -695,14 +692,7 @@ void Sema::CheckCXXThisCapture(SourceLocation Loc) {
|
|||
continue;
|
||||
}
|
||||
// This context can't implicitly capture 'this'; fail out.
|
||||
// (We need to delay the diagnostic in the
|
||||
// PotentiallyPotentiallyEvaluated case because it doesn't apply to
|
||||
// unevaluated contexts.)
|
||||
if (ExprEvalContexts.back().Context == PotentiallyPotentiallyEvaluated)
|
||||
ExprEvalContexts.back()
|
||||
.addDiagnostic(Loc, PDiag(diag::err_implicit_this_capture));
|
||||
else
|
||||
Diag(Loc, diag::err_implicit_this_capture);
|
||||
Diag(Loc, diag::err_implicit_this_capture);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -74,14 +74,10 @@ enum IMAKind {
|
|||
/// context is not an instance method.
|
||||
IMA_Unresolved_StaticContext,
|
||||
|
||||
// The reference is an instance data member access, which is allowed
|
||||
// because we're in C++11 mode and the context is unevaluated.
|
||||
IMA_Field_Uneval_StaticContext,
|
||||
|
||||
// The reference is an instance data member access, which may be allowed
|
||||
// because we're in C++11 mode and the context may be unevaluated
|
||||
// (i.e. the context is PotentiallyPotentiallyEvaluated).
|
||||
IMA_Field_PPE_StaticContext,
|
||||
// The reference refers to a field which is not a member of the containing
|
||||
// class, which is allowed because we're in C++11 mode and the context is
|
||||
// unevaluated.
|
||||
IMA_Field_Uneval_Context,
|
||||
|
||||
/// All possible referrents are instance members and the current
|
||||
/// context is not an instance method.
|
||||
|
@ -158,9 +154,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
|
|||
const Sema::ExpressionEvaluationContextRecord& record
|
||||
= SemaRef.ExprEvalContexts.back();
|
||||
if (record.Context == Sema::Unevaluated)
|
||||
return IMA_Field_Uneval_StaticContext;
|
||||
if (record.Context == Sema::PotentiallyPotentiallyEvaluated)
|
||||
return IMA_Field_PPE_StaticContext;
|
||||
return IMA_Field_Uneval_Context;
|
||||
}
|
||||
|
||||
return IMA_Error_StaticContext;
|
||||
|
@ -196,8 +190,7 @@ static IMAKind ClassifyImplicitMemberAccess(Sema &SemaRef,
|
|||
static void DiagnoseInstanceReference(Sema &SemaRef,
|
||||
const CXXScopeSpec &SS,
|
||||
NamedDecl *rep,
|
||||
const DeclarationNameInfo &nameInfo,
|
||||
bool DelayPPEDiag = false) {
|
||||
const DeclarationNameInfo &nameInfo) {
|
||||
SourceLocation Loc = nameInfo.getLoc();
|
||||
SourceRange Range(Loc);
|
||||
if (SS.isSet()) Range.setBegin(SS.getRange().getBegin());
|
||||
|
@ -206,29 +199,17 @@ static void DiagnoseInstanceReference(Sema &SemaRef,
|
|||
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext)) {
|
||||
if (MD->isStatic()) {
|
||||
// "invalid use of member 'x' in static member function"
|
||||
if (DelayPPEDiag)
|
||||
SemaRef.ExprEvalContexts.back().addDiagnostic(Loc,
|
||||
SemaRef.PDiag(diag::err_invalid_member_use_in_static_method)
|
||||
<< Range << nameInfo.getName());
|
||||
else
|
||||
SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
|
||||
<< Range << nameInfo.getName();
|
||||
SemaRef.Diag(Loc, diag::err_invalid_member_use_in_static_method)
|
||||
<< Range << nameInfo.getName();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (DelayPPEDiag)
|
||||
SemaRef.ExprEvalContexts.back().addDiagnostic(Loc,
|
||||
SemaRef.PDiag(diag::err_invalid_non_static_member_use)
|
||||
<< nameInfo.getName() << Range);
|
||||
else
|
||||
SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
|
||||
<< nameInfo.getName() << Range;
|
||||
SemaRef.Diag(Loc, diag::err_invalid_non_static_member_use)
|
||||
<< nameInfo.getName() << Range;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!DelayPPEDiag && "Only need to delay diagnostic for fields");
|
||||
|
||||
SemaRef.Diag(Loc, diag::err_member_call_without_object) << Range;
|
||||
}
|
||||
|
||||
|
@ -246,15 +227,10 @@ Sema::BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
|
|||
case IMA_Unresolved:
|
||||
return BuildImplicitMemberExpr(SS, R, TemplateArgs, false);
|
||||
|
||||
case IMA_Field_PPE_StaticContext:
|
||||
DiagnoseInstanceReference(*this, SS, R.getRepresentativeDecl(),
|
||||
R.getLookupNameInfo(), /*DelayPPEDiag*/true);
|
||||
// FALL-THROUGH
|
||||
|
||||
case IMA_Static:
|
||||
case IMA_Mixed_StaticContext:
|
||||
case IMA_Unresolved_StaticContext:
|
||||
case IMA_Field_Uneval_StaticContext:
|
||||
case IMA_Field_Uneval_Context:
|
||||
if (TemplateArgs)
|
||||
return BuildTemplateIdExpr(SS, R, false, *TemplateArgs);
|
||||
return BuildDeclarationNameExpr(SS, R, false);
|
||||
|
|
|
@ -1057,40 +1057,23 @@ 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 Autoreleasing and
|
||||
// don't give error.
|
||||
// If we are in an unevaluated context, like sizeof, skip adding a
|
||||
// qualification.
|
||||
} else if (S.ExprEvalContexts.back().Context == Sema::Unevaluated ||
|
||||
S.ExprEvalContexts.back().Context == Sema::ConstantEvaluated) {
|
||||
implicitLifetime = Qualifiers::OCL_Autoreleasing;
|
||||
return type;
|
||||
|
||||
// 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()) {
|
||||
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));
|
||||
}
|
||||
S.DelayedDiagnostics.add(
|
||||
sema::DelayedDiagnostic::makeForbiddenType(loc,
|
||||
diag::err_arc_indirect_no_ownership, type, isReference));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
|
||||
}
|
||||
implicitLifetime = Qualifiers::OCL_Autoreleasing;
|
||||
}
|
||||
|
|
|
@ -6878,11 +6878,11 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
|
|||
E->getLocEnd());
|
||||
}
|
||||
|
||||
// We don't know whether the expression is potentially evaluated until
|
||||
// after we perform semantic analysis, so the expression is potentially
|
||||
// We don't know whether the subexpression is potentially evaluated until
|
||||
// after we perform semantic analysis. We speculatively assume it is
|
||||
// unevaluated; it will get fixed later if the subexpression is in fact
|
||||
// potentially evaluated.
|
||||
EnterExpressionEvaluationContext Unevaluated(SemaRef,
|
||||
Sema::PotentiallyPotentiallyEvaluated);
|
||||
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
|
||||
|
||||
ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
|
||||
if (SubExpr.isInvalid())
|
||||
|
|
|
@ -27,3 +27,4 @@ namespace std {
|
|||
class Poly { virtual ~Poly(); };
|
||||
const std::type_info& k = typeid(S::m);
|
||||
const std::type_info& m = typeid(*(Poly*)S::m); // expected-error {{invalid use of nonstatic data member}}
|
||||
const std::type_info& n = typeid(*(Poly*)(0*sizeof S::m));
|
Loading…
Reference in New Issue