[cfe-commits] [PATCH] Model C++11 rules for odr-use for variables correctly
Eli Friedman
eli.friedman at gmail.com
Tue Jan 31 21:43:11 PST 2012
On Sat, Jan 28, 2012 at 12:35 AM, John McCall <rjmccall at apple.com> wrote:
> On Jan 27, 2012, at 7:56 PM, Eli Friedman wrote:
>> On Fri, Jan 27, 2012 at 3:26 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
>>> On Fri, Jan 27, 2012 at 3:12 PM, John McCall <rjmccall at apple.com> wrote:
>>>> On Jan 27, 2012, at 2:53 PM, Eli Friedman wrote:
>>>>> On Thu, Jan 26, 2012 at 7:29 PM, John McCall <rjmccall at apple.com> wrote:
>>>>>> On Jan 24, 2012, at 9:34 PM, Eli Friedman wrote:
>>>>>>> Patch attached. Basically, this is implementing the C++11 rules in
>>>>>>> [basic.def.odr]p2 for variables allowed in constant expressions.
>>>>>>> (Those rules don't matter so much for most code given how we do code
>>>>>>> generation, but we have to get the rules exactly right to get implicit
>>>>>>> capture in lambda expressions working correctly.)
>>>>>>>
>>>>>>> I don't really like this patch, but it seems like it is necessary.
>>>>>>
>>>>>> Yeah, I'm really not happy with this. Obvious alternative: mark ODR use
>>>>>> at the DRE creation site unless the object is not already marked and it
>>>>>> meets the constant-loading criteria. If it does, flag that this full-expression
>>>>>> contains a potential reference, then walk back over the completed
>>>>>> full-expression looking for PE DREs not direct operands of L2R casts.
>>>>>
>>>>> Is there any existing hook that actually triggers where I need it to?
>>>>> MaybeCreateExprWithCleanups seems close... but doesn't quite cover
>>>>> everything.
>>>>
>>>> What's missing?
>>>
>>> In essence, things which are constant-expressions in the C++ grammar
>>> are missing. Not too hard to add them, I guess.
>>
>> New version attached; it doesn't pass regression tests because I still
>> need to add a hook to catch VLA array bounds attached to declarations,
>> but is this the direction you were thinking of?
>
> That's the general idea, although I didn't carefully look at where you added
> the calls. Two things, though:
> - The dynamic optimization of not doing this traversal unless we saw
> a DeclRef of a not-yet-used-but-const-and-whatever-else declaration
> is going to be quite important.
> - isDependentContext() is actually both (a) surprisingly expensive and
> (b) extremely easy for Sema to cache.
New version attached; similar approach, but avoiding the recursive
walk by keeping the relevant expressions in a side-table. This is
essentially complete except for one issue: I think I need some sort of
stack to prevent incorrect odr-use marking in some edge cases.
-Eli
-------------- next part --------------
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h (revision 149309)
+++ include/clang/Sema/Sema.h (working copy)
@@ -233,6 +233,8 @@
/// element type here is ExprWithCleanups::Object.
SmallVector<BlockDecl*, 8> ExprCleanupObjects;
+ llvm::SmallPtrSet<Expr*, 8> MaybeODRUseExprs;
+
/// \brief Stack containing information about each of the nested
/// function, block, and method scopes that are currently active.
///
@@ -2265,7 +2267,23 @@
ExprResult TranformToPotentiallyEvaluated(Expr *E);
ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
- void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
+ // Functions for marking a declaration referenced. These functions also
+ // contain the relevant logic for marking if a reference to a function or
+ // variable is an odr-use (in the C++11 sense). There are separate variants
+ // for expressions referring to a decl; these exist because odr-use marking
+ // needs to be delayed for some constant variables when we build one of the
+ // named expressions.
+ void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D);
+ void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func);
+ void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var);
+ void MarkBlockDeclRefReferenced(BlockDeclRefExpr *E);
+ void MarkDeclRefReferenced(DeclRefExpr *E);
+ void MarkMemberReferenced(MemberExpr *E);
+
+ void UpdateMarkingForLValueToRValue(Expr *E);
+ void CleanupVarDeclMarking();
+
+
void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
void MarkDeclarationsReferencedInExpr(Expr *E);
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp (revision 149309)
+++ lib/Sema/SemaDeclCXX.cpp (working copy)
@@ -2382,14 +2382,14 @@
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
- SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param);
-
Expr *CopyCtorArg =
DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
SourceLocation(), Param,
Constructor->getLocation(), ParamType,
VK_LValue, 0);
+ SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));
+
// Cast to the base class to avoid ambiguities.
QualType ArgTy =
SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
@@ -2454,8 +2454,6 @@
ParmVarDecl *Param = Constructor->getParamDecl(0);
QualType ParamType = Param->getType().getNonReferenceType();
- SemaRef.MarkDeclarationReferenced(Constructor->getLocation(), Param);
-
// Suppress copying zero-width bitfields.
if (Field->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
return false;
@@ -2465,6 +2463,8 @@
SourceLocation(), Param,
Loc, ParamType, VK_LValue, 0);
+ SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));
+
if (Moving) {
MemberExprBase = CastForMoving(SemaRef, MemberExprBase);
}
@@ -2796,7 +2796,7 @@
Constructor->setCtorInitializers(initializer);
if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) {
- MarkDeclarationReferenced(Initializer->getSourceLocation(), Dtor);
+ MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor);
DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());
}
@@ -3272,7 +3272,7 @@
<< Field->getDeclName()
<< FieldType);
- MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
}
llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;
@@ -3304,7 +3304,7 @@
<< Base->getType()
<< Base->getSourceRange());
- MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
}
// Virtual bases.
@@ -3332,7 +3332,7 @@
PDiag(diag::err_access_dtor_vbase)
<< VBase->getType());
- MarkDeclarationReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
+ MarkFunctionReferenced(Location, const_cast<CXXDestructorDecl*>(Dtor));
}
}
@@ -5306,7 +5306,7 @@
if (FindDeallocationFunction(Loc, RD, Name, OperatorDelete))
return true;
- MarkDeclarationReferenced(Loc, OperatorDelete);
+ MarkFunctionReferenced(Loc, OperatorDelete);
Destructor->setOperatorDelete(OperatorDelete);
}
@@ -9030,7 +9030,7 @@
CheckNonNullArguments(NonNull, ExprArgs.get(), ConstructLoc);
}
- MarkDeclarationReferenced(ConstructLoc, Constructor);
+ MarkFunctionReferenced(ConstructLoc, Constructor);
return Owned(CXXConstructExpr::Create(Context, DeclInitType, ConstructLoc,
Constructor, Elidable, Exprs, NumExprs,
HadMultipleCandidates, RequiresZeroInit,
@@ -9052,7 +9052,7 @@
Expr *Temp = TempResult.takeAs<Expr>();
CheckImplicitConversions(Temp, VD->getLocation());
- MarkDeclarationReferenced(VD->getLocation(), Constructor);
+ MarkFunctionReferenced(VD->getLocation(), Constructor);
Temp = MaybeCreateExprWithCleanups(Temp);
VD->setInit(Temp);
@@ -9068,7 +9068,7 @@
if (ClassDecl->isDependentContext()) return;
CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
- MarkDeclarationReferenced(VD->getLocation(), Destructor);
+ MarkFunctionReferenced(VD->getLocation(), Destructor);
CheckDestructorAccess(VD->getLocation(), Destructor,
PDiag(diag::err_access_dtor_var)
<< VD->getDeclName()
@@ -10905,7 +10905,7 @@
// C++ [basic.def.odr]p2:
// [...] A virtual member function is used if it is not pure. [...]
if (MD->isVirtual() && !MD->isPure())
- MarkDeclarationReferenced(Loc, MD);
+ MarkFunctionReferenced(Loc, MD);
}
// Only classes that have virtual bases need a VTT.
@@ -10965,7 +10965,7 @@
->getAs<RecordType>()) {
CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
- MarkDeclarationReferenced(Field->getLocation(), Destructor);
+ MarkFunctionReferenced(Field->getLocation(), Destructor);
CheckDestructorAccess(Field->getLocation(), Destructor,
PDiag(diag::err_access_dtor_ivar)
<< Context.getBaseElementType(Field->getType()));
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h (revision 149441)
+++ lib/Sema/TreeTransform.h (working copy)
@@ -5949,7 +5949,7 @@
// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
- SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+ SemaRef.MarkDeclRefReferenced(E);
return SemaRef.Owned(E);
}
@@ -6293,7 +6293,8 @@
// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
- SemaRef.MarkDeclarationReferenced(E->getMemberLoc(), Member);
+ SemaRef.MarkMemberReferenced(E);
+
return SemaRef.Owned(E);
}
@@ -7117,11 +7118,11 @@
// Mark any declarations we need as referenced.
// FIXME: instantiation-specific.
if (Constructor)
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
if (OperatorNew)
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorNew);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorNew);
if (OperatorDelete)
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
if (E->isArray() && Constructor &&
!E->getAllocatedType()->isDependentType()) {
@@ -7130,7 +7131,7 @@
if (const RecordType *RecordT = ElementType->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordT->getDecl());
if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(Record)) {
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), Destructor);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), Destructor);
}
}
}
@@ -7202,15 +7203,15 @@
// Mark any declarations we need as referenced.
// FIXME: instantiation-specific.
if (OperatorDelete)
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), OperatorDelete);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), OperatorDelete);
if (!E->getArgument()->isTypeDependent()) {
QualType Destroyed = SemaRef.Context.getBaseElementType(
E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- SemaRef.MarkDeclarationReferenced(E->getLocStart(),
- SemaRef.LookupDestructor(Record));
+ SemaRef.MarkFunctionReferenced(E->getLocStart(),
+ SemaRef.LookupDestructor(Record));
}
}
@@ -7540,7 +7541,7 @@
!ArgumentChanged) {
// Mark the constructor as referenced.
// FIXME: Instantiation-specific
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
return SemaRef.Owned(E);
}
@@ -7601,7 +7602,7 @@
Constructor == E->getConstructor() &&
!ArgumentChanged) {
// FIXME: Instantiation-specific
- SemaRef.MarkDeclarationReferenced(E->getLocStart(), Constructor);
+ SemaRef.MarkFunctionReferenced(E->getLocStart(), Constructor);
return SemaRef.MaybeBindToTemporary(E);
}
@@ -8253,7 +8254,7 @@
ND == E->getDecl()) {
// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
- SemaRef.MarkDeclarationReferenced(E->getLocation(), ND);
+ SemaRef.MarkBlockDeclRefReferenced(E);
return SemaRef.Owned(E);
}
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp (revision 149309)
+++ lib/Sema/SemaExprCXX.cpp (working copy)
@@ -645,7 +645,7 @@
if (!Destructor)
return Owned(E);
- MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+ MarkFunctionReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_exception) << Ty);
return Owned(E);
@@ -1185,16 +1185,16 @@
// Mark the new and delete operators as referenced.
if (OperatorNew)
- MarkDeclarationReferenced(StartLoc, OperatorNew);
+ MarkFunctionReferenced(StartLoc, OperatorNew);
if (OperatorDelete)
- MarkDeclarationReferenced(StartLoc, OperatorDelete);
+ MarkFunctionReferenced(StartLoc, OperatorDelete);
// C++0x [expr.new]p17:
// If the new expression creates an array of objects of class type,
// access and ambiguity control are done for the destructor.
if (ArraySize && Constructor) {
if (CXXDestructorDecl *dtor = LookupDestructor(Constructor->getParent())) {
- MarkDeclarationReferenced(StartLoc, dtor);
+ MarkFunctionReferenced(StartLoc, dtor);
CheckDestructorAccess(StartLoc, dtor,
PDiag(diag::err_access_dtor)
<< Context.getBaseElementType(AllocType));
@@ -1514,7 +1514,7 @@
case OR_Success: {
// Got one!
FunctionDecl *FnDecl = Best->Function;
- MarkDeclarationReferenced(StartLoc, FnDecl);
+ MarkFunctionReferenced(StartLoc, FnDecl);
// The first argument is size_t, and the first parameter must be size_t,
// too. This is checked on declaration and can be assumed. (It can't be
// asserted on, though, since invalid decls are left in there.)
@@ -1953,7 +1953,7 @@
if (!PointeeRD->hasTrivialDestructor())
if (CXXDestructorDecl *Dtor = LookupDestructor(PointeeRD)) {
- MarkDeclarationReferenced(StartLoc,
+ MarkFunctionReferenced(StartLoc,
const_cast<CXXDestructorDecl*>(Dtor));
DiagnoseUseOfDecl(Dtor, StartLoc);
}
@@ -2002,7 +2002,7 @@
return ExprError();
}
- MarkDeclarationReferenced(StartLoc, OperatorDelete);
+ MarkFunctionReferenced(StartLoc, OperatorDelete);
// Check access and ambiguity of operator delete and destructor.
if (PointeeRD) {
@@ -2046,7 +2046,7 @@
ConditionVar->getType().getNonReferenceType(),
VK_LValue));
- MarkDeclarationReferenced(ConditionVar->getLocation(), ConditionVar);
+ MarkDeclRefReferenced(cast<DeclRefExpr>(Condition.get()));
if (ConvertToBoolean) {
Condition = CheckBooleanCondition(Condition.take(), StmtLoc);
@@ -3606,7 +3606,7 @@
break;
RHS = move(RHSRes);
if (Best->Function)
- Self.MarkDeclarationReferenced(QuestionLoc, Best->Function);
+ Self.MarkFunctionReferenced(QuestionLoc, Best->Function);
return false;
}
@@ -4207,7 +4207,7 @@
CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor);
if (Destructor) {
- MarkDeclarationReferenced(E->getExprLoc(), Destructor);
+ MarkFunctionReferenced(E->getExprLoc(), Destructor);
CheckDestructorAccess(E->getExprLoc(), Destructor,
PDiag(diag::err_access_dtor_temp)
<< E->getType());
@@ -4229,6 +4229,8 @@
Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) {
assert(SubExpr && "sub expression can't be null!");
+ CleanupVarDeclMarking();
+
unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects;
assert(ExprCleanupObjects.size() >= FirstCleanup);
assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup);
@@ -4248,6 +4250,8 @@
Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) {
assert(SubStmt && "sub statement can't be null!");
+ CleanupVarDeclMarking();
+
if (!ExprNeedsCleanups)
return SubStmt;
@@ -4684,7 +4688,7 @@
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
- MarkDeclarationReferenced(Exp.get()->getLocStart(), Method);
+ MarkFunctionReferenced(Exp.get()->getLocStart(), Method);
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, 0, 0, ResultType, VK,
Exp.get()->getLocEnd());
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp (revision 149309)
+++ lib/Sema/SemaDeclAttr.cpp (working copy)
@@ -2160,7 +2160,7 @@
}
D->addAttr(::new (S.Context) CleanupAttr(Attr.getRange(), S.Context, FD));
- S.MarkDeclarationReferenced(Attr.getParameterLoc(), FD);
+ S.MarkFunctionReferenced(Attr.getParameterLoc(), FD);
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp (revision 149309)
+++ lib/Sema/SemaInit.cpp (working copy)
@@ -3156,7 +3156,7 @@
// This is the overload that will actually be used for the initialization, so
// mark it as used.
- S.MarkDeclarationReferenced(DeclLoc, Function);
+ S.MarkFunctionReferenced(DeclLoc, Function);
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
@@ -3679,7 +3679,7 @@
}
FunctionDecl *Function = Best->Function;
- S.MarkDeclarationReferenced(DeclLoc, Function);
+ S.MarkFunctionReferenced(DeclLoc, Function);
bool HadMultipleCandidates = (CandidateSet.size() > 1);
if (isa<CXXConstructorDecl>(Function)) {
@@ -4388,7 +4388,7 @@
return S.Owned(CurInitExpr);
}
- S.MarkDeclarationReferenced(Loc, Constructor);
+ S.MarkFunctionReferenced(Loc, Constructor);
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
@@ -4531,7 +4531,7 @@
// An explicitly-constructed temporary, e.g., X(1, 2).
unsigned NumExprs = ConstructorArgs.size();
Expr **Exprs = (Expr **)ConstructorArgs.take();
- S.MarkDeclarationReferenced(Loc, Constructor);
+ S.MarkFunctionReferenced(Loc, Constructor);
S.DiagnoseUseOfDecl(Constructor, Loc);
TypeSourceInfo *TSInfo = Entity.getTypeSourceInfo();
@@ -4899,7 +4899,7 @@
= S.LookupDestructor(cast<CXXRecordDecl>(Record->getDecl()));
S.CheckDestructorAccess(CurInit.get()->getLocStart(), Destructor,
S.PDiag(diag::err_access_dtor_temp) << T);
- S.MarkDeclarationReferenced(CurInit.get()->getLocStart(), Destructor);
+ S.MarkFunctionReferenced(CurInit.get()->getLocStart(), Destructor);
S.DiagnoseUseOfDecl(Destructor, CurInit.get()->getLocStart());
}
}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp (revision 149309)
+++ lib/Sema/SemaDecl.cpp (working copy)
@@ -7298,6 +7298,8 @@
assert(ExprCleanupObjects.empty() && "Leftover temporaries in function");
assert(!ExprNeedsCleanups && "Unaccounted cleanups in function");
+ assert(MaybeODRUseExprs.empty() &&
+ "Leftover expressions for odr-use checking");
}
if (!IsInstantiation)
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp (revision 149309)
+++ lib/Sema/SemaTemplate.cpp (working copy)
@@ -3630,7 +3630,7 @@
// Create the template argument.
Converted = TemplateArgument(Entity->getCanonicalDecl());
- S.MarkDeclarationReferenced(Arg->getLocStart(), Entity);
+ S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity);
return false;
}
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp (revision 149309)
+++ lib/Sema/SemaOverload.cpp (working copy)
@@ -2893,7 +2893,7 @@
// Record the standard conversion we used and the conversion function.
if (CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(Best->Function)) {
- S.MarkDeclarationReferenced(From->getLocStart(), Constructor);
+ S.MarkFunctionReferenced(From->getLocStart(), Constructor);
// C++ [over.ics.user]p1:
// If the user-defined conversion is specified by a
@@ -2923,7 +2923,7 @@
}
if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
- S.MarkDeclarationReferenced(From->getLocStart(), Conversion);
+ S.MarkFunctionReferenced(From->getLocStart(), Conversion);
// C++ [over.ics.user]p1:
//
@@ -3793,7 +3793,7 @@
return false;
if (Best->Function)
- S.MarkDeclarationReferenced(DeclLoc, Best->Function);
+ S.MarkFunctionReferenced(DeclLoc, Best->Function);
ICS.setUserDefined();
ICS.UserDefined.Before = Best->Conversions[0].Standard;
ICS.UserDefined.After = Best->FinalConversion;
@@ -8817,7 +8817,7 @@
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
- MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn);
+ MarkFunctionReferenced(AddressOfExpr->getLocStart(), Fn);
if (Complain)
CheckAddressOfMemberAccess(AddressOfExpr, FoundResult);
}
@@ -9380,7 +9380,7 @@
switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
case OR_Success: {
FunctionDecl *FDecl = Best->Function;
- MarkDeclarationReferenced(Fn->getExprLoc(), FDecl);
+ MarkFunctionReferenced(Fn->getExprLoc(), FDecl);
CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
@@ -9534,7 +9534,7 @@
// We matched an overloaded operator. Build a call to that
// operator.
- MarkDeclarationReferenced(OpLoc, FnDecl);
+ MarkFunctionReferenced(OpLoc, FnDecl);
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
@@ -9755,7 +9755,7 @@
// We matched an overloaded operator. Build a call to that
// operator.
- MarkDeclarationReferenced(OpLoc, FnDecl);
+ MarkFunctionReferenced(OpLoc, FnDecl);
// Convert the arguments.
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(FnDecl)) {
@@ -9962,7 +9962,7 @@
// We matched an overloaded operator. Build a call to that
// operator.
- MarkDeclarationReferenced(LLoc, FnDecl);
+ MarkFunctionReferenced(LLoc, FnDecl);
CheckMemberOperatorAccess(LLoc, Args[0], Args[1], Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LLoc);
@@ -10211,7 +10211,7 @@
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
- MarkDeclarationReferenced(UnresExpr->getMemberLoc(), Method);
+ MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
@@ -10476,7 +10476,7 @@
RParenLoc);
}
- MarkDeclarationReferenced(LParenLoc, Best->Function);
+ MarkFunctionReferenced(LParenLoc, Best->Function);
CheckMemberOperatorAccess(LParenLoc, Object.get(), 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, LParenLoc);
@@ -10666,7 +10666,7 @@
return ExprError();
}
- MarkDeclarationReferenced(OpLoc, Best->Function);
+ MarkFunctionReferenced(OpLoc, Best->Function);
CheckMemberOperatorAccess(OpLoc, Base, 0, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, OpLoc);
Index: lib/Sema/SemaExprMember.cpp
===================================================================
--- lib/Sema/SemaExprMember.cpp (revision 149309)
+++ lib/Sema/SemaExprMember.cpp (working copy)
@@ -776,7 +776,8 @@
}
/// \brief Build a MemberExpr AST node.
-static MemberExpr *BuildMemberExpr(ASTContext &C, Expr *Base, bool isArrow,
+static MemberExpr *BuildMemberExpr(Sema &SemaRef,
+ ASTContext &C, Expr *Base, bool isArrow,
const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
ValueDecl *Member,
@@ -786,9 +787,12 @@
ExprValueKind VK, ExprObjectKind OK,
const TemplateArgumentListInfo *TemplateArgs = 0) {
assert((!isArrow || Base->isRValue()) && "-> base must be a pointer rvalue");
- return MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
- TemplateKWLoc, Member, FoundDecl, MemberNameInfo,
- TemplateArgs, Ty, VK, OK);
+ MemberExpr *E =
+ MemberExpr::Create(C, Base, isArrow, SS.getWithLocInContext(C),
+ TemplateKWLoc, Member, FoundDecl, MemberNameInfo,
+ TemplateArgs, Ty, VK, OK);
+ SemaRef.MarkMemberReferenced(E);
+ return E;
}
ExprResult
@@ -908,9 +912,8 @@
BaseExpr, OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, Var);
- return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Var, FoundDecl, MemberNameInfo,
+ return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
+ TemplateKWLoc, Var, FoundDecl, MemberNameInfo,
Var->getType().getNonReferenceType(),
VK_LValue, OK_Ordinary));
}
@@ -926,17 +929,16 @@
type = MemberFn->getType();
}
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
- return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- MemberFn, FoundDecl, MemberNameInfo,
- type, valueKind, OK_Ordinary));
+ return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
+ TemplateKWLoc, MemberFn, FoundDecl,
+ MemberNameInfo, type, valueKind,
+ OK_Ordinary));
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
- MarkDeclarationReferenced(MemberLoc, MemberDecl);
- return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS, TemplateKWLoc,
- Enum, FoundDecl, MemberNameInfo,
+ return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, SS,
+ TemplateKWLoc, Enum, FoundDecl, MemberNameInfo,
Enum->getType(), VK_RValue, OK_Ordinary));
}
@@ -1540,13 +1542,12 @@
MemberType = S.Context.getQualifiedType(MemberType, Combined);
}
- S.MarkDeclarationReferenced(MemberNameInfo.getLoc(), Field);
ExprResult Base =
S.PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),
FoundDecl, Field);
if (Base.isInvalid())
return ExprError();
- return S.Owned(BuildMemberExpr(S.Context, Base.take(), IsArrow, SS,
+ return S.Owned(BuildMemberExpr(S, S.Context, Base.take(), IsArrow, SS,
/*TemplateKWLoc=*/SourceLocation(),
Field, FoundDecl, MemberNameInfo,
MemberType, VK, OK));
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp (revision 149309)
+++ lib/Sema/SemaExpr.cpp (working copy)
@@ -404,6 +404,8 @@
if (T.hasQualifiers())
T = T.getUnqualifiedType();
+ UpdateMarkingForLValueToRValue(E);
+
ExprResult Res = Owned(ImplicitCastExpr::Create(Context, T, CK_LValueToRValue,
E, 0, VK_RValue));
@@ -1330,8 +1332,6 @@
return CR_Error;
}
- S.MarkDeclarationReferenced(loc, var);
-
// The BlocksAttr indicates the variable is bound by-reference.
bool byRef = var->hasAttr<BlocksAttr>();
@@ -1410,6 +1410,8 @@
NameInfo.getLoc(), true);
}
+ S.MarkBlockDeclRefReferenced(BDRE);
+
return S.Owned(BDRE);
}
@@ -1441,13 +1443,13 @@
}
}
- MarkDeclarationReferenced(NameInfo.getLoc(), D);
+ DeclRefExpr *E = DeclRefExpr::Create(Context,
+ SS ? SS->getWithLocInContext(Context)
+ : NestedNameSpecifierLoc(),
+ SourceLocation(),
+ D, NameInfo, Ty, VK);
- Expr *E = DeclRefExpr::Create(Context,
- SS ? SS->getWithLocInContext(Context)
- : NestedNameSpecifierLoc(),
- SourceLocation(),
- D, NameInfo, Ty, VK);
+ MarkDeclRefReferenced(E);
// Just in case we're building an illegal pointer-to-member.
FieldDecl *FD = dyn_cast<FieldDecl>(D);
@@ -2003,7 +2005,7 @@
if (SelfExpr.isInvalid())
return ExprError();
- MarkDeclarationReferenced(Loc, IV);
+ MarkAnyDeclReferenced(Loc, IV);
return Owned(new (Context)
ObjCIvarRefExpr(IV, IV->getType(), Loc,
SelfExpr.take(), true, true));
@@ -3741,7 +3743,7 @@
DeclRefExpr *ConfigDR = new (Context) DeclRefExpr(
ConfigDecl, ConfigQTy, VK_LValue, LLLLoc);
- MarkDeclarationReferenced(LLLLoc, ConfigDecl);
+ MarkFunctionReferenced(LLLLoc, ConfigDecl);
return ActOnCallExpr(S, ConfigDR, LLLLoc, ExecConfig, GGGLoc, 0,
/*IsExecConfig=*/true);
@@ -9447,6 +9449,7 @@
ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects,
ExprCleanupObjects.end());
ExprNeedsCleanups = Rec.ParentNeedsCleanups;
+ CleanupVarDeclMarking();
// Otherwise, merge the contexts together.
} else {
@@ -9467,55 +9470,47 @@
return TranformToPotentiallyEvaluated(E);
}
-/// \brief Note that the given declaration was referenced in the source code.
-///
-/// This routine should be invoke whenever a given declaration is referenced
-/// in the source code, and where that reference occurred. If this declaration
-/// reference means that the the declaration is used (C++ [basic.def.odr]p2,
-/// C99 6.9p3), then the declaration will be marked as used.
-///
-/// \param Loc the location where the declaration was referenced.
-///
-/// \param D the declaration that has been referenced by the source code.
-void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
- assert(D && "No declaration?");
-
- D->setReferenced();
-
- if (D->isUsed(false))
- return;
-
- if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D))
- return;
-
+bool IsPotentiallyEvaluatedContext(Sema &SemaRef) {
// Do not mark anything as "used" within a dependent context; wait for
// an instantiation.
- if (CurContext->isDependentContext())
- return;
+ if (SemaRef.CurContext->isDependentContext())
+ return false;
- switch (ExprEvalContexts.back().Context) {
- case Unevaluated:
+ switch (SemaRef.ExprEvalContexts.back().Context) {
+ case Sema::Unevaluated:
// We are in an expression that is not potentially evaluated; do nothing.
// (Depending on how you read the standard, we actually do need to do
// something here for null pointer constants, but the standard's
// definition of a null pointer constant is completely crazy.)
- return;
+ return false;
- case ConstantEvaluated:
- case PotentiallyEvaluated:
+ case Sema::ConstantEvaluated:
+ case Sema::PotentiallyEvaluated:
// We are in a potentially evaluated expression (or a constant-expression
// in C++03); we need to do implicit template instantiation, implicitly
// define class members, and mark most declarations as used.
- break;
+ return true;
- case PotentiallyEvaluatedIfUsed:
+ case Sema::PotentiallyEvaluatedIfUsed:
// Referenced declarations will only be used if the construct in the
// containing expression is used.
- return;
+ return false;
}
+}
+void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) {
+ assert(Func && "No function?");
+
+ Func->setReferenced();
+
+ if (Func->isUsed(false))
+ return;
+
+ if (!IsPotentiallyEvaluatedContext(*this))
+ return;
+
// Note that this declaration has been used.
- if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Func)) {
if (Constructor->isDefaulted()) {
if (Constructor->isDefaultConstructor()) {
if (Constructor->isTrivial())
@@ -9532,12 +9527,13 @@
}
MarkVTableUsed(Loc, Constructor->getParent());
- } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {
+ } else if (CXXDestructorDecl *Destructor =
+ dyn_cast<CXXDestructorDecl>(Func)) {
if (Destructor->isDefaulted() && !Destructor->isUsed(false))
DefineImplicitDestructor(Loc, Destructor);
if (Destructor->isVirtual())
MarkVTableUsed(Loc, Destructor->getParent());
- } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(D)) {
+ } else if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(Func)) {
if (MethodDecl->isDefaulted() && MethodDecl->isOverloadedOperator() &&
MethodDecl->getOverloadedOperator() == OO_Equal) {
if (!MethodDecl->isUsed(false)) {
@@ -9549,101 +9545,183 @@
} else if (MethodDecl->isVirtual())
MarkVTableUsed(Loc, MethodDecl->getParent());
}
- if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- // Recursive functions should be marked when used from another function.
- if (CurContext == Function) return;
- // Implicit instantiation of function templates and member functions of
- // class templates.
- if (Function->isImplicitlyInstantiable()) {
- bool AlreadyInstantiated = false;
- if (FunctionTemplateSpecializationInfo *SpecInfo
- = Function->getTemplateSpecializationInfo()) {
- if (SpecInfo->getPointOfInstantiation().isInvalid())
- SpecInfo->setPointOfInstantiation(Loc);
- else if (SpecInfo->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation)
- AlreadyInstantiated = true;
- } else if (MemberSpecializationInfo *MSInfo
- = Function->getMemberSpecializationInfo()) {
- if (MSInfo->getPointOfInstantiation().isInvalid())
- MSInfo->setPointOfInstantiation(Loc);
- else if (MSInfo->getTemplateSpecializationKind()
- == TSK_ImplicitInstantiation)
- AlreadyInstantiated = true;
- }
+ // Recursive functions should be marked when used from another function.
+ // FIXME: Is this really right?
+ if (CurContext == Func) return;
- if (!AlreadyInstantiated) {
- if (isa<CXXRecordDecl>(Function->getDeclContext()) &&
- cast<CXXRecordDecl>(Function->getDeclContext())->isLocalClass())
- PendingLocalImplicitInstantiations.push_back(std::make_pair(Function,
- Loc));
- else if (Function->getTemplateInstantiationPattern()->isConstexpr())
- // Do not defer instantiations of constexpr functions, to avoid the
- // expression evaluator needing to call back into Sema if it sees a
- // call to such a function.
- InstantiateFunctionDefinition(Loc, Function);
- else
- PendingInstantiations.push_back(std::make_pair(Function, Loc));
- }
- } else {
- // Walk redefinitions, as some of them may be instantiable.
- for (FunctionDecl::redecl_iterator i(Function->redecls_begin()),
- e(Function->redecls_end()); i != e; ++i) {
- if (!i->isUsed(false) && i->isImplicitlyInstantiable())
- MarkDeclarationReferenced(Loc, *i);
- }
+ // Implicit instantiation of function templates and member functions of
+ // class templates.
+ if (Func->isImplicitlyInstantiable()) {
+ bool AlreadyInstantiated = false;
+ if (FunctionTemplateSpecializationInfo *SpecInfo
+ = Func->getTemplateSpecializationInfo()) {
+ if (SpecInfo->getPointOfInstantiation().isInvalid())
+ SpecInfo->setPointOfInstantiation(Loc);
+ else if (SpecInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
+ AlreadyInstantiated = true;
+ } else if (MemberSpecializationInfo *MSInfo
+ = Func->getMemberSpecializationInfo()) {
+ if (MSInfo->getPointOfInstantiation().isInvalid())
+ MSInfo->setPointOfInstantiation(Loc);
+ else if (MSInfo->getTemplateSpecializationKind()
+ == TSK_ImplicitInstantiation)
+ AlreadyInstantiated = true;
}
- // Keep track of used but undefined functions.
- if (!Function->isPure() && !Function->hasBody() &&
- Function->getLinkage() != ExternalLinkage) {
- SourceLocation &old = UndefinedInternals[Function->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
+ if (!AlreadyInstantiated) {
+ if (isa<CXXRecordDecl>(Func->getDeclContext()) &&
+ cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass())
+ PendingLocalImplicitInstantiations.push_back(std::make_pair(Func,
+ Loc));
+ else if (Func->getTemplateInstantiationPattern()->isConstexpr())
+ // Do not defer instantiations of constexpr functions, to avoid the
+ // expression evaluator needing to call back into Sema if it sees a
+ // call to such a function.
+ InstantiateFunctionDefinition(Loc, Func);
+ else
+ PendingInstantiations.push_back(std::make_pair(Func, Loc));
}
+ } else {
+ // Walk redefinitions, as some of them may be instantiable.
+ for (FunctionDecl::redecl_iterator i(Func->redecls_begin()),
+ e(Func->redecls_end()); i != e; ++i) {
+ if (!i->isUsed(false) && i->isImplicitlyInstantiable())
+ MarkFunctionReferenced(Loc, *i);
+ }
+ }
- Function->setUsed(true);
- return;
+ // Keep track of used but undefined functions.
+ if (!Func->isPure() && !Func->hasBody() &&
+ Func->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = UndefinedInternals[Func->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
}
- if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
- // Implicit instantiation of static data members of class templates.
- if (Var->isStaticDataMember() &&
- Var->getInstantiatedFromStaticDataMember()) {
- MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
- assert(MSInfo && "Missing member specialization information?");
- if (MSInfo->getPointOfInstantiation().isInvalid() &&
- MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
- MSInfo->setPointOfInstantiation(Loc);
- // This is a modification of an existing AST node. Notify listeners.
- if (ASTMutationListener *L = getASTMutationListener())
- L->StaticDataMemberInstantiated(Var);
- if (Var->isUsableInConstantExpressions())
- // Do not defer instantiations of variables which could be used in a
- // constant expression.
- InstantiateStaticDataMemberDefinition(Loc, Var);
- else
- PendingInstantiations.push_back(std::make_pair(Var, Loc));
- }
+ Func->setUsed(true);
+}
+
+static void InstantiateVarDecl(Sema &SemaRef, VarDecl *Var,
+ SourceLocation Loc) {
+ // Implicit instantiation of static data members of class templates.
+ if (Var->isStaticDataMember() &&
+ Var->getInstantiatedFromStaticDataMember()) {
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "Missing member specialization information?");
+ if (MSInfo->getPointOfInstantiation().isInvalid() &&
+ MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) {
+ MSInfo->setPointOfInstantiation(Loc);
+ // This is a modification of an existing AST node. Notify listeners.
+ if (ASTMutationListener *L = SemaRef.getASTMutationListener())
+ L->StaticDataMemberInstantiated(Var);
+ if (Var->isUsableInConstantExpressions())
+ // Do not defer instantiations of variables which could be used in a
+ // constant expression.
+ SemaRef.InstantiateStaticDataMemberDefinition(Loc, Var);
+ else
+ SemaRef.PendingInstantiations.push_back(std::make_pair(Var, Loc));
}
+ }
+}
- // Keep track of used but undefined variables. We make a hole in
- // the warning for static const data members with in-line
- // initializers.
- // FIXME: The hole we make for static const data members is too wide!
- // We need to implement the C++11 rules for odr-used.
- if (Var->hasDefinition() == VarDecl::DeclarationOnly
- && Var->getLinkage() != ExternalLinkage
- && !(Var->isStaticDataMember() && Var->hasInit())) {
- SourceLocation &old = UndefinedInternals[Var->getCanonicalDecl()];
- if (old.isInvalid()) old = Loc;
+static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,
+ SourceLocation Loc) {
+ // Keep track of used but undefined variables.
+ if (Var->hasDefinition() == VarDecl::DeclarationOnly &&
+ Var->getLinkage() != ExternalLinkage) {
+ SourceLocation &old = SemaRef.UndefinedInternals[Var->getCanonicalDecl()];
+ if (old.isInvalid()) old = Loc;
+ }
+
+ Var->setUsed(true);
+}
+
+void Sema::UpdateMarkingForLValueToRValue(Expr *E) {
+ MaybeODRUseExprs.erase(E->IgnoreParens());
+}
+
+void Sema::CleanupVarDeclMarking() {
+ for (llvm::SmallPtrSetIterator<Expr*> i = MaybeODRUseExprs.begin(),
+ e = MaybeODRUseExprs.end();
+ i != e; ++i) {
+ VarDecl *Var;
+ SourceLocation Loc;
+ if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(*i)) {
+ Var = BDRE->getDecl();
+ Loc = BDRE->getLocation();
+ } else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(*i)) {
+ Var = cast<VarDecl>(DRE->getDecl());
+ Loc = DRE->getLocation();
+ } else if (MemberExpr *ME = dyn_cast<MemberExpr>(*i)) {
+ Var = cast<VarDecl>(ME->getMemberDecl());
+ Loc = ME->getMemberLoc();
+ } else {
+ llvm_unreachable("Unexpcted expression");
}
- D->setUsed(true);
+ MarkVarDeclODRUsed(*this, Var, Loc);
+ }
+
+ MaybeODRUseExprs.clear();
+}
+
+void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
+ VarDecl *Var, Expr *E) {
+ Var->setReferenced();
+
+ if (Var->isUsed(false))
return;
+
+ if (!IsPotentiallyEvaluatedContext(SemaRef))
+ return;
+
+ InstantiateVarDecl(SemaRef, Var, Loc);
+
+ const VarDecl *DefVD;
+ if (E && !isa<ParmVarDecl>(Var) &&
+ Var->isUsableInConstantExpressions() &&
+ Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE())
+ SemaRef.MaybeODRUseExprs.insert(E);
+ else
+ MarkVarDeclODRUsed(SemaRef, Var, Loc);
+}
+
+void Sema::MarkVariableReferenced(SourceLocation Loc, VarDecl *Var) {
+ DoMarkVarDeclReferenced(*this, Loc, Var, 0);
+}
+
+static void MarkExprReferenced(Sema &SemaRef, SourceLocation Loc,
+ Decl *D, Expr *E) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
+ DoMarkVarDeclReferenced(SemaRef, Loc, Var, E);
+ return;
}
+
+ SemaRef.MarkAnyDeclReferenced(Loc, D);
}
+void Sema::MarkBlockDeclRefReferenced(BlockDeclRefExpr *E) {
+ MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E);
+}
+
+void Sema::MarkDeclRefReferenced(DeclRefExpr *E) {
+ MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E);
+}
+
+void Sema::MarkMemberReferenced(MemberExpr *E) {
+ MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
+}
+
+void Sema::MarkAnyDeclReferenced(SourceLocation Loc, Decl *D) {
+ if (VarDecl *VD = dyn_cast<VarDecl>(D))
+ MarkVariableReferenced(Loc, VD);
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ MarkFunctionReferenced(Loc, FD);
+ else
+ D->setReferenced();
+}
+
namespace {
// Mark all of the declarations referenced
// FIXME: Not fully implemented yet! We need to have a better understanding
@@ -9665,7 +9743,7 @@
bool MarkReferencedDecls::TraverseTemplateArgument(
const TemplateArgument &Arg) {
if (Arg.getKind() == TemplateArgument::Declaration) {
- S.MarkDeclarationReferenced(Loc, Arg.getAsDecl());
+ S.MarkAnyDeclReferenced(Loc, Arg.getAsDecl());
}
return Inherited::TraverseTemplateArgument(Arg);
@@ -9698,37 +9776,37 @@
explicit EvaluatedExprMarker(Sema &S) : Inherited(S.Context), S(S) { }
void VisitDeclRefExpr(DeclRefExpr *E) {
- S.MarkDeclarationReferenced(E->getLocation(), E->getDecl());
+ S.MarkDeclRefReferenced(E);
}
void VisitMemberExpr(MemberExpr *E) {
- S.MarkDeclarationReferenced(E->getMemberLoc(), E->getMemberDecl());
+ S.MarkMemberReferenced(E);
Inherited::VisitMemberExpr(E);
}
void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
- S.MarkDeclarationReferenced(E->getLocStart(),
+ S.MarkFunctionReferenced(E->getLocStart(),
const_cast<CXXDestructorDecl*>(E->getTemporary()->getDestructor()));
Visit(E->getSubExpr());
}
void VisitCXXNewExpr(CXXNewExpr *E) {
if (E->getConstructor())
- S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor());
+ S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor());
if (E->getOperatorNew())
- S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorNew());
+ S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorNew());
if (E->getOperatorDelete())
- S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete());
+ S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
Inherited::VisitCXXNewExpr(E);
}
void VisitCXXDeleteExpr(CXXDeleteExpr *E) {
if (E->getOperatorDelete())
- S.MarkDeclarationReferenced(E->getLocStart(), E->getOperatorDelete());
+ S.MarkFunctionReferenced(E->getLocStart(), E->getOperatorDelete());
QualType Destroyed = S.Context.getBaseElementType(E->getDestroyedType());
if (const RecordType *DestroyedRec = Destroyed->getAs<RecordType>()) {
CXXRecordDecl *Record = cast<CXXRecordDecl>(DestroyedRec->getDecl());
- S.MarkDeclarationReferenced(E->getLocStart(),
+ S.MarkFunctionReferenced(E->getLocStart(),
S.LookupDestructor(Record));
}
@@ -9736,12 +9814,12 @@
}
void VisitCXXConstructExpr(CXXConstructExpr *E) {
- S.MarkDeclarationReferenced(E->getLocStart(), E->getConstructor());
+ S.MarkFunctionReferenced(E->getLocStart(), E->getConstructor());
Inherited::VisitCXXConstructExpr(E);
}
void VisitBlockDeclRefExpr(BlockDeclRefExpr *E) {
- S.MarkDeclarationReferenced(E->getLocation(), E->getDecl());
+ //S.MarkFunctionReferenced(E->getLocation(), E->getDecl());
}
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {
More information about the cfe-commits
mailing list