aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2013-02-12 08:08:54 +0000
committerNick Lewycky <nicholas@mxc.ca>2013-02-12 08:08:54 +0000
commit3c86a5c2f60d4f68afde96e2138b6933b30d6aa8 (patch)
treea0c5180bb7f1e6bc768481cfabfd1076ee4245bd
parent06098586f1de7ec5e12ccc3a2291782dee99cd1e (diff)
The meat of this patch is in BuildCXXMemberCalLExpr where we make it use
MarkMemberReferenced instead of marking functions referenced directly. An audit of callers to MarkFunctionReferenced and DiagnoseUseOfDecl also caused a few other changes: * don't mark functions odr-used when considering them for an initialization sequence. Do mark them referenced though. * the function nominated by the cleanup attribute should be diagnosed. * operator new/delete should be diagnosed when building a 'new' expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@174951 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclAttr.cpp1
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaExprCXX.cpp10
-rw-r--r--lib/Sema/SemaInit.cpp11
-rw-r--r--lib/Sema/SemaOverload.cpp2
-rw-r--r--test/Sema/attr-cleanup.c4
-rw-r--r--test/SemaCXX/attr-deprecated.cpp13
-rw-r--r--test/SemaCXX/undefined-internal.cpp37
8 files changed, 68 insertions, 14 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 4c8d098158..97d1ea2cf1 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2849,6 +2849,7 @@ static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
CleanupAttr(Attr.getRange(), S.Context, FD,
Attr.getAttributeSpellingListIndex()));
S.MarkFunctionReferenced(Attr.getParameterLoc(), FD);
+ S.DiagnoseUseOfDecl(FD, Attr.getParameterLoc());
}
/// Handle __attribute__((format_arg((idx)))) attribute based on
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index f6c6fe118e..191683d33d 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -11210,7 +11210,9 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
if (Method->isPure())
OdrUse = false;
}
- MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E, OdrUse);
+ SourceLocation Loc = E->getMemberLoc().isValid() ?
+ E->getMemberLoc() : E->getLocStart();
+ MarkExprReferenced(*this, Loc, E->getMemberDecl(), E, OdrUse);
}
/// \brief Perform marking for a reference to an arbitrary declaration. It
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 7f24af8be1..49d66113dc 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -1376,10 +1376,14 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
}
// Mark the new and delete operators as referenced.
- if (OperatorNew)
+ if (OperatorNew) {
+ DiagnoseUseOfDecl(OperatorNew, StartLoc);
MarkFunctionReferenced(StartLoc, OperatorNew);
- if (OperatorDelete)
+ }
+ if (OperatorDelete) {
+ DiagnoseUseOfDecl(OperatorDelete, StartLoc);
MarkFunctionReferenced(StartLoc, OperatorDelete);
+ }
// C++0x [expr.new]p17:
// If the new expression creates an array of objects of class type,
@@ -5335,12 +5339,12 @@ ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl,
VK_RValue, OK_Ordinary);
if (HadMultipleCandidates)
ME->setHadMultipleCandidates(true);
+ MarkMemberReferenced(ME);
QualType ResultType = Method->getResultType();
ExprValueKind VK = Expr::getValueKindForType(ResultType);
ResultType = ResultType.getNonLValueExprType(Context);
- MarkFunctionReferenced(Exp.get()->getLocStart(), Method);
CXXMemberCallExpr *CE =
new (Context) CXXMemberCallExpr(Context, ME, MultiExprArg(), ResultType, VK,
Exp.get()->getLocEnd());
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 0612c73f89..1b69872417 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -3262,10 +3262,9 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
return Result;
FunctionDecl *Function = Best->Function;
-
- // This is the overload that will actually be used for the initialization, so
- // mark it as used.
- S.MarkFunctionReferenced(DeclLoc, Function);
+ // This is the overload that will be used for this initialization step if we
+ // use this initialization. Mark it as referenced.
+ Function->setReferenced();
// Compute the returned type of the conversion.
if (isa<CXXConversionDecl>(Function))
@@ -3831,7 +3830,7 @@ static void TryUserDefinedConversion(Sema &S,
}
FunctionDecl *Function = Best->Function;
- S.MarkFunctionReferenced(DeclLoc, Function);
+ Function->setReferenced();
bool HadMultipleCandidates = (CandidateSet.size() > 1);
if (isa<CXXConstructorDecl>(Function)) {
@@ -4609,8 +4608,6 @@ static ExprResult CopyObject(Sema &S,
return S.Owned(CurInitExpr);
}
- S.MarkFunctionReferenced(Loc, Constructor);
-
// Determine the arguments required to actually perform the
// constructor call (we might have derived-to-base conversions, or
// the copy constructor may have default arguments).
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 6fa4137970..c2e0d6f809 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -9916,7 +9916,6 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
switch (OverloadResult) {
case OR_Success: {
FunctionDecl *FDecl = (*Best)->Function;
- SemaRef.MarkFunctionReferenced(Fn->getExprLoc(), FDecl);
SemaRef.CheckUnresolvedLookupAccess(ULE, (*Best)->FoundDecl);
SemaRef.DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl);
@@ -10799,7 +10798,6 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Best)) {
case OR_Success:
Method = cast<CXXMethodDecl>(Best->Function);
- MarkFunctionReferenced(UnresExpr->getMemberLoc(), Method);
FoundDecl = Best->FoundDecl;
CheckUnresolvedMemberAccess(UnresExpr, Best->FoundDecl);
DiagnoseUseOfDecl(Best->FoundDecl, UnresExpr->getNameLoc());
diff --git a/test/Sema/attr-cleanup.c b/test/Sema/attr-cleanup.c
index 59ebbfc459..991822e402 100644
--- a/test/Sema/attr-cleanup.c
+++ b/test/Sema/attr-cleanup.c
@@ -38,3 +38,7 @@ void t4() {
__attribute((cleanup(c4))) void* g;
}
+void c5(void*) __attribute__((deprecated)); // expected-note{{'c5' declared here}}
+void t5() {
+ int i __attribute__((cleanup(c5))); // expected-warning {{'c5' is deprecated}}
+}
diff --git a/test/SemaCXX/attr-deprecated.cpp b/test/SemaCXX/attr-deprecated.cpp
index f3d818a75f..2d730a8eed 100644
--- a/test/SemaCXX/attr-deprecated.cpp
+++ b/test/SemaCXX/attr-deprecated.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -verify -fexceptions
class A {
void f() __attribute__((deprecated)); // expected-note 2 {{declared here}}
void g(A* a);
@@ -233,3 +233,14 @@ namespace test6 {
x = D<int>::d1; // expected-warning {{'d1' is deprecated}}
}
}
+
+namespace test7 {
+ struct X {
+ void* operator new(unsigned long) __attribute__((deprecated)); // expected-note{{'operator new' declared here}}
+ void operator delete(void *) __attribute__((deprecated)); // expected-note{{'operator delete' declared here}}
+ };
+
+ void test() {
+ X *x = new X; // expected-warning{{'operator new' is deprecated}} expected-warning{{'operator delete' is deprecated}}
+ }
+}
diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp
index 40ab33cac4..e8810adadf 100644
--- a/test/SemaCXX/undefined-internal.cpp
+++ b/test/SemaCXX/undefined-internal.cpp
@@ -269,3 +269,40 @@ namespace test11 {
(void)b1->member; // expected-note {{used here}}
}
}
+
+namespace test12 {
+ class T1 {}; class T2 {}; class T3 {}; class T4 {}; class T5 {}; class T6 {};
+ class T7 {};
+
+ namespace {
+ struct Cls {
+ virtual void f(int) = 0;
+ virtual void f(int, double) = 0;
+ void g(int); // expected-warning {{function 'test12::<anonymous namespace>::Cls::g' has internal linkage but is not defined}}
+ void g(int, double);
+ virtual operator T1() = 0;
+ virtual operator T2() = 0;
+ virtual operator T3&() = 0;
+ operator T4(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator T4' has internal linkage but is not defined}}
+ operator T5(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator T5' has internal linkage but is not defined}}
+ operator T6&(); // expected-warning {{function 'test12::<anonymous namespace>::Cls::operator class test12::T6 &' has internal linkage but is not defined}}
+ };
+
+ struct Cls2 {
+ Cls2(T7); // expected-warning {{function 'test12::<anonymous namespace>::Cls2::Cls2' has internal linkage but is not defined}}
+ };
+ }
+
+ void test(Cls &c) {
+ c.f(7);
+ c.g(7); // expected-note {{used here}}
+ (void)static_cast<T1>(c);
+ T2 t2 = c;
+ T3 &t3 = c;
+ (void)static_cast<T4>(c); // expected-note {{used here}}
+ T5 t5 = c; // expected-note {{used here}}
+ T6 &t6 = c; // expected-note {{used here}}
+
+ Cls2 obj1((T7())); // expected-note {{used here}}
+ }
+}