The meat of this patch is in BuildCXXMemberCalLExpr where we make it use
authorNick Lewycky <nicholas@mxc.ca>
Tue, 12 Feb 2013 08:08:54 +0000 (08:08 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Tue, 12 Feb 2013 08:08:54 +0000 (08:08 +0000)
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.

llvm-svn: 174951

clang/lib/Sema/SemaDeclAttr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaInit.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/Sema/attr-cleanup.c
clang/test/SemaCXX/attr-deprecated.cpp
clang/test/SemaCXX/undefined-internal.cpp

index 4c8d098..97d1ea2 100644 (file)
@@ -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
index f6c6fe1..191683d 100644 (file)
@@ -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
index 7f24af8..49d6611 100644 (file)
@@ -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());
index 0612c73..1b69872 100644 (file)
@@ -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).
index 6fa4137..c2e0d6f 100644 (file)
@@ -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());
index 59ebbfc..991822e 100644 (file)
@@ -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}}
+}
index f3d818a..2d730a8 100644 (file)
@@ -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}}
+  }
+}
index 40ab33c..e8810ad 100644 (file)
@@ -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}}
+  }
+}