[cfe-commits] r127253 - in /cfe/trunk: include/clang/AST/DeclCXX.h include/clang/Sema/DeclSpec.h lib/AST/ASTImporter.cpp lib/AST/DeclCXX.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Serialization/ASTReaderDecl.cpp test/Index/annotate-context-sensitive.cpp test/Index/annotate-tokens.m tools/libclang/CIndex.cpp

Douglas Gregor dgregor at apple.com
Tue Mar 8 09:10:18 PST 2011


Author: dgregor
Date: Tue Mar  8 11:10:18 2011
New Revision: 127253

URL: http://llvm.org/viewvc/llvm-project?rev=127253&view=rev
Log:
Teach libclang's token-annotation logic about context-sensitive
keywords for Objective-C+ and C++0x. 

Added:
    cfe/trunk/test/Index/annotate-context-sensitive.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/test/Index/annotate-tokens.m
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Mar  8 11:10:18 2011
@@ -1037,19 +1037,24 @@
   CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc,
                 const DeclarationNameInfo &NameInfo,
                 QualType T, TypeSourceInfo *TInfo,
-                bool isStatic, StorageClass SCAsWritten, bool isInline)
+                bool isStatic, StorageClass SCAsWritten, bool isInline,
+                SourceLocation EndLocation)
     : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo,
                    (isStatic ? SC_Static : SC_None),
-                   SCAsWritten, isInline) {}
+                   SCAsWritten, isInline) {
+      if (EndLocation.isValid())
+        setRangeEnd(EndLocation);
+    }
 
 public:
   static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
                                SourceLocation StartLoc,
                                const DeclarationNameInfo &NameInfo,
                                QualType T, TypeSourceInfo *TInfo,
-                               bool isStatic = false,
-                               StorageClass SCAsWritten = SC_None,
-                               bool isInline = false);
+                               bool isStatic,
+                               StorageClass SCAsWritten,
+                               bool isInline,
+                               SourceLocation EndLocation);
 
   bool isStatic() const { return getStorageClass() == SC_Static; }
   bool isInstance() const { return !isStatic(); }
@@ -1403,7 +1408,7 @@
                      bool isExplicitSpecified, bool isInline, 
                      bool isImplicitlyDeclared)
     : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false,
-                    SC_None, isInline),
+                    SC_None, isInline, SourceLocation()),
       IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false),
       CtorInitializers(0), NumCtorInitializers(0) {
     setImplicit(isImplicitlyDeclared);
@@ -1598,7 +1603,7 @@
                     QualType T, TypeSourceInfo *TInfo,
                     bool isInline, bool isImplicitlyDeclared)
     : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false,
-                    SC_None, isInline),
+                    SC_None, isInline, SourceLocation()),
       ImplicitlyDefined(false), OperatorDelete(0) {
     setImplicit(isImplicitlyDeclared);
   }
@@ -1660,9 +1665,10 @@
   CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc,
                     const DeclarationNameInfo &NameInfo,
                     QualType T, TypeSourceInfo *TInfo,
-                    bool isInline, bool isExplicitSpecified)
+                    bool isInline, bool isExplicitSpecified,
+                    SourceLocation EndLocation)
     : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false,
-                    SC_None, isInline),
+                    SC_None, isInline, EndLocation),
       IsExplicitSpecified(isExplicitSpecified) { }
 
 public:
@@ -1671,7 +1677,8 @@
                                    SourceLocation StartLoc,
                                    const DeclarationNameInfo &NameInfo,
                                    QualType T, TypeSourceInfo *TInfo,
-                                   bool isInline, bool isExplicit);
+                                   bool isInline, bool isExplicit,
+                                   SourceLocation EndLocation);
 
   /// IsExplicitSpecified - Whether this conversion function declaration is 
   /// marked "explicit", meaning that it can only be applied when the user

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Tue Mar  8 11:10:18 2011
@@ -1649,10 +1649,13 @@
 
   static const char *getSpecifierName(Specifier VS);
 
+  SourceLocation getLastLocation() const { return LastLocation; }
+  
 private:
   unsigned Specifiers;
 
   SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc;
+  SourceLocation LastLocation;
 };
 
 /// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq.

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Mar  8 11:10:18 2011
@@ -2389,7 +2389,8 @@
                                            D->getInnerLocStart(),
                                            NameInfo, T, TInfo,
                                            D->isInlineSpecified(),
-                                           FromConversion->isExplicit());
+                                           FromConversion->isExplicit(),
+                                           Importer.Import(D->getLocEnd()));
   } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
     ToFunction = CXXMethodDecl::Create(Importer.getToContext(), 
                                        cast<CXXRecordDecl>(DC),
@@ -2397,7 +2398,8 @@
                                        NameInfo, T, TInfo,
                                        Method->isStatic(),
                                        Method->getStorageClassAsWritten(),
-                                       Method->isInlineSpecified());
+                                       Method->isInlineSpecified(),
+                                       Importer.Import(D->getLocEnd()));
   } else {
     ToFunction = FunctionDecl::Create(Importer.getToContext(), DC,
                                       D->getInnerLocStart(),

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Mar  8 11:10:18 2011
@@ -887,9 +887,10 @@
                       SourceLocation StartLoc,
                       const DeclarationNameInfo &NameInfo,
                       QualType T, TypeSourceInfo *TInfo,
-                      bool isStatic, StorageClass SCAsWritten, bool isInline) {
+                      bool isStatic, StorageClass SCAsWritten, bool isInline,
+                      SourceLocation EndLocation) {
   return new (C) CXXMethodDecl(CXXMethod, RD, StartLoc, NameInfo, T, TInfo,
-                               isStatic, SCAsWritten, isInline);
+                               isStatic, SCAsWritten, isInline, EndLocation);
 }
 
 bool CXXMethodDecl::isUsualDeallocationFunction() const {
@@ -1255,7 +1256,8 @@
 CXXConversionDecl *
 CXXConversionDecl::Create(ASTContext &C, EmptyShell Empty) {
   return new (C) CXXConversionDecl(0, SourceLocation(), DeclarationNameInfo(),
-                                   QualType(), 0, false, false);
+                                   QualType(), 0, false, false,
+                                   SourceLocation());
 }
 
 CXXConversionDecl *
@@ -1263,12 +1265,13 @@
                           SourceLocation StartLoc,
                           const DeclarationNameInfo &NameInfo,
                           QualType T, TypeSourceInfo *TInfo,
-                          bool isInline, bool isExplicit) {
+                          bool isInline, bool isExplicit,
+                          SourceLocation EndLocation) {
   assert(NameInfo.getName().getNameKind()
          == DeclarationName::CXXConversionFunctionName &&
          "Name must refer to a conversion function");
   return new (C) CXXConversionDecl(RD, StartLoc, NameInfo, T, TInfo,
-                                   isInline, isExplicit);
+                                   isInline, isExplicit, EndLocation);
 }
 
 LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Tue Mar  8 11:10:18 2011
@@ -796,6 +796,8 @@
 
 bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
                                   const char *&PrevSpec) {
+  LastLocation = Loc;
+  
   if (Specifiers & VS) {
     PrevSpec = getSpecifierName(VS);
     return true;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Mar  8 11:10:18 2011
@@ -3711,7 +3711,8 @@
       NewFD = CXXConversionDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                         D.getSourceRange().getBegin(),
                                         NameInfo, R, TInfo,
-                                        isInline, isExplicit);
+                                        isInline, isExplicit,
+                                        SourceLocation());
 
       isVirtualOkay = true;
     } else if (DC->isRecord()) {
@@ -3747,7 +3748,8 @@
       NewFD = CXXMethodDecl::Create(Context, cast<CXXRecordDecl>(DC),
                                     D.getSourceRange().getBegin(),
                                     NameInfo, R, TInfo,
-                                    isStatic, SCAsWritten, isInline);
+                                    isStatic, SCAsWritten, isInline,
+                                    SourceLocation());
 
       isVirtualOkay = !isStatic;
     } else {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Mar  8 11:10:18 2011
@@ -1069,6 +1069,12 @@
       MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context));
   }
 
+  if (VS.getLastLocation().isValid()) {
+    // Update the end location of a method that has a virt-specifiers.
+    if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member))
+      MD->setRangeEnd(VS.getLastLocation());
+  }
+      
   CheckOverrideControl(Member);
 
   assert((Name || isInstField) && "No identifier for non-field ?");
@@ -5407,7 +5413,8 @@
                             Context.getFunctionType(RetType, &ArgType, 1, EPI),
                             /*TInfo=*/0, /*isStatic=*/false,
                             /*StorageClassAsWritten=*/SC_None,
-                            /*isInline=*/true);
+                            /*isInline=*/true,
+                            SourceLocation());
   CopyAssignment->setAccess(AS_public);
   CopyAssignment->setImplicit();
   CopyAssignment->setTrivial(ClassDecl->hasTrivialCopyAssignment());

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Mar  8 11:10:18 2011
@@ -1316,13 +1316,15 @@
     Method = CXXConversionDecl::Create(SemaRef.Context, Record,
                                        StartLoc, NameInfo, T, TInfo,
                                        Conversion->isInlineSpecified(),
-                                       Conversion->isExplicit());
+                                       Conversion->isExplicit(),
+                                       Conversion->getLocEnd());
   } else {
     Method = CXXMethodDecl::Create(SemaRef.Context, Record,
                                    StartLoc, NameInfo, T, TInfo,
                                    D->isStatic(),
                                    D->getStorageClassAsWritten(),
-                                   D->isInlineSpecified());
+                                   D->isInlineSpecified(),
+                                   D->getLocEnd());
   }
 
   if (QualifierLoc)

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Mar  8 11:10:18 2011
@@ -1489,7 +1489,8 @@
     break;
   case DECL_CXX_METHOD:
     D = CXXMethodDecl::Create(*Context, 0, SourceLocation(),
-                              DeclarationNameInfo(), QualType(), 0);
+                              DeclarationNameInfo(), QualType(), 0,
+                              false, SC_None, false, SourceLocation());
     break;
   case DECL_CXX_CONSTRUCTOR:
     D = CXXConstructorDecl::Create(*Context, Decl::EmptyShell());

Added: cfe/trunk/test/Index/annotate-context-sensitive.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-context-sensitive.cpp?rev=127253&view=auto
==============================================================================
--- cfe/trunk/test/Index/annotate-context-sensitive.cpp (added)
+++ cfe/trunk/test/Index/annotate-context-sensitive.cpp Tue Mar  8 11:10:18 2011
@@ -0,0 +1,42 @@
+class Base {
+public:
+  virtual void f();
+};
+
+class Derived final : public Base {
+  virtual void f() override final;
+
+  struct final { };
+};
+
+typedef int override;
+struct Base2 {
+  virtual int override();
+};
+
+struct Derived2 : Base2 {
+  ::override override() override;
+};
+
+// RUN: c-index-test -test-annotate-tokens=%s:6:1:19:1 %s | FileCheck -check-prefix=CHECK-OVERRIDE-FINAL %s
+
+// CHECK-OVERRIDE-FINAL: Keyword: "class" [6:1 - 6:6] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Identifier: "Derived" [6:7 - 6:14] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Keyword: "final" [6:15 - 6:20] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Punctuation: ":" [6:21 - 6:22] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Keyword: "public" [6:23 - 6:29] C++ base class specifier=class Base:1:7 [access=public isVirtual=false]
+// CHECK-OVERRIDE-FINAL: Identifier: "Base" [6:30 - 6:34] TypeRef=class Base:1:7
+// CHECK-OVERRIDE-FINAL: Punctuation: "{" [6:35 - 6:36] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Keyword: "virtual" [7:3 - 7:10] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Keyword: "void" [7:11 - 7:15] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Identifier: "f" [7:16 - 7:17] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Punctuation: "(" [7:17 - 7:18] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Punctuation: ")" [7:18 - 7:19] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Keyword: "override" [7:20 - 7:28] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Keyword: "final" [7:29 - 7:34] CXXMethod=f:7:16 [Overrides @3:16]
+// CHECK-OVERRIDE-FINAL: Punctuation: ";" [7:34 - 7:35] ClassDecl=Derived:6:7 (Definition)
+// CHECK-OVERRIDE-FINAL: Keyword: "struct" [9:3 - 9:9] StructDecl=final:9:10 (Definition)
+// CHECK-OVERRIDE-FINAL: Identifier: "final" [9:10 - 9:15] StructDecl=final:9:10 (Definition)
+// CHECK-OVERRIDE-FINAL: Punctuation: "{" [9:16 - 9:17] StructDecl=final:9:10 (Definition)
+// CHECK-OVERRIDE-FINAL: Punctuation: "}" [9:18 - 9:19] StructDecl=final:9:10 (Definition)
+// CHECK-OVERRIDE-FINAL: Punctuation: ";" [9:19 - 9:20] ClassDecl=Derived:6:7 (Definition)

Modified: cfe/trunk/test/Index/annotate-tokens.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/annotate-tokens.m?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/test/Index/annotate-tokens.m (original)
+++ cfe/trunk/test/Index/annotate-tokens.m Tue Mar  8 11:10:18 2011
@@ -30,12 +30,12 @@
 // Since there are no source ranges for attributes, we currently don't
 // annotate them.
 @interface IBActionTests
-- (IBAction) actionMethod:(id)arg;
+- (IBAction) actionMethod:(in id)arg;
 - (void)foo:(int)x;
 @end
 extern int ibaction_test(void);
 @implementation IBActionTests
-- (IBAction) actionMethod:(id)arg
+- (IBAction) actionMethod:(in id)arg
 {
     ibaction_test();
     [self foo:0];
@@ -231,10 +231,11 @@
 // CHECK: Identifier: "actionMethod" [33:14 - 33:26] ObjCInstanceMethodDecl=actionMethod::33:1
 // CHECK: Punctuation: ":" [33:26 - 33:27] ObjCInstanceMethodDecl=actionMethod::33:1
 // CHECK: Punctuation: "(" [33:27 - 33:28] ObjCInstanceMethodDecl=actionMethod::33:1
-// CHECK: Identifier: "id" [33:28 - 33:30] TypeRef=id:0:0
-// CHECK: Punctuation: ")" [33:30 - 33:31] ParmDecl=arg:33:31 (Definition)
-// CHECK: Identifier: "arg" [33:31 - 33:34] ParmDecl=arg:33:31 (Definition)
-// CHECK: Punctuation: ";" [33:34 - 33:35] ObjCInstanceMethodDecl=actionMethod::33:1
+// CHECK: Keyword: "in" [33:28 - 33:30] ObjCInstanceMethodDecl=actionMethod::33:1
+// CHECK: Identifier: "id" [33:31 - 33:33] TypeRef=id:0:0
+// CHECK: Punctuation: ")" [33:33 - 33:34] ParmDecl=arg:33:34 (Definition)
+// CHECK: Identifier: "arg" [33:34 - 33:37] ParmDecl=arg:33:34 (Definition)
+// CHECK: Punctuation: ";" [33:37 - 33:38] ObjCInstanceMethodDecl=actionMethod::33:1
 // CHECK: Punctuation: "-" [34:1 - 34:2] ObjCInstanceMethodDecl=foo::34:1
 // CHECK: Punctuation: "(" [34:3 - 34:4] ObjCInstanceMethodDecl=foo::34:1
 // CHECK: Keyword: "void" [34:4 - 34:8] ObjCInstanceMethodDecl=foo::34:1
@@ -264,10 +265,10 @@
 // CHECK: Punctuation: ")" [38:12 - 38:13] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
 // CHECK: Identifier: "actionMethod" [38:14 - 38:26] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
 // CHECK: Punctuation: ":" [38:26 - 38:27] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
-// CHECK: Punctuation: "(" [38:27 - 38:28] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition)
-// CHECK: Identifier: "id" [38:28 - 38:30] TypeRef=id:0:0
-// CHECK: Punctuation: ")" [38:30 - 38:31] ParmDecl=arg:38:31 (Definition)
-// CHECK: Identifier: "arg" [38:31 - 38:34] ParmDecl=arg:38:31 (Definition)
+// CHECK: Keyword: "in" [38:28 - 38:30] ObjCInstanceMethodDecl=actionMethod::38:1 (Definition) [Overrides @33:1]
+// CHECK: Identifier: "id" [38:31 - 38:33] TypeRef=id:0:0
+// CHECK: Punctuation: ")" [38:33 - 38:34] ParmDecl=arg:38:34 (Definition)
+// CHECK: Identifier: "arg" [38:34 - 38:37] ParmDecl=arg:38:34 (Definition)
 // CHECK: Punctuation: "{" [39:1 - 39:2] UnexposedStmt=
 // CHECK: Identifier: "ibaction_test" [40:5 - 40:18] DeclRefExpr=ibaction_test:36:12
 // CHECK: Punctuation: "(" [40:18 - 40:19] CallExpr=ibaction_test:36:12
@@ -484,16 +485,16 @@
 // CHECK: Punctuation: "@" [110:1 - 110:2] ObjCPropertyDecl=foo:110:33
 // CHECK: Keyword: "property" [110:2 - 110:10] ObjCPropertyDecl=foo:110:33
 // CHECK: Punctuation: "(" [110:11 - 110:12] ObjCPropertyDecl=foo:110:33
-// CHECK: Identifier: "readonly" [110:12 - 110:20] ObjCPropertyDecl=foo:110:33
+// CHECK: Keyword: "readonly" [110:12 - 110:20] ObjCPropertyDecl=foo:110:33
 // CHECK: Punctuation: "," [110:20 - 110:21] ObjCPropertyDecl=foo:110:33
-// CHECK: Identifier: "copy" [110:22 - 110:26] ObjCPropertyDecl=foo:110:33
+// CHECK: Keyword: "copy" [110:22 - 110:26] ObjCPropertyDecl=foo:110:33
 // CHECK: Punctuation: ")" [110:26 - 110:27] ObjCPropertyDecl=foo:110:33
 // CHECK: Identifier: "Foo" [110:28 - 110:31] ObjCClassRef=Foo:1:12
 // CHECK: Punctuation: "*" [110:32 - 110:33] ObjCPropertyDecl=foo:110:33
 // CHECK: Identifier: "foo" [110:33 - 110:36] ObjCPropertyDecl=foo:110:33
 // CHECK: Keyword: "property" [111:2 - 111:10] ObjCPropertyDecl=foo2:111:27
 // CHECK: Punctuation: "(" [111:11 - 111:12] ObjCPropertyDecl=foo2:111:27
-// CHECK: Identifier: "readonly" [111:12 - 111:20] ObjCPropertyDecl=foo2:111:27
+// CHECK: Keyword: "readonly" [111:12 - 111:20] ObjCPropertyDecl=foo2:111:27
 // CHECK: Punctuation: ")" [111:20 - 111:21] ObjCPropertyDecl=foo2:111:27
 // CHECK: Identifier: "Foo" [111:22 - 111:25] ObjCClassRef=Foo:1:12
 // CHECK: Punctuation: "*" [111:26 - 111:27] ObjCPropertyDecl=foo2:111:27
@@ -539,9 +540,9 @@
 // CHECK-PROP-AFTER-METHOD: Punctuation: "@" [136:1 - 136:2] ObjCPropertyDecl=blah:136:38
 // CHECK-PROP-AFTER-METHOD: Keyword: "property" [136:2 - 136:10] ObjCPropertyDecl=blah:136:38
 // CHECK-PROP-AFTER-METHOD: Punctuation: "(" [136:11 - 136:12] ObjCPropertyDecl=blah:136:38
-// CHECK-PROP-AFTER-METHOD: Identifier: "readonly" [136:12 - 136:20] ObjCPropertyDecl=blah:136:38
+// CHECK-PROP-AFTER-METHOD: Keyword: "readonly" [136:12 - 136:20] ObjCPropertyDecl=blah:136:38
 // CHECK-PROP-AFTER-METHOD: Punctuation: "," [136:20 - 136:21] ObjCPropertyDecl=blah:136:38
-// CHECK-PROP-AFTER-METHOD: Identifier: "nonatomic" [136:22 - 136:31] ObjCPropertyDecl=blah:136:38
+// CHECK-PROP-AFTER-METHOD: Keyword: "nonatomic" [136:22 - 136:31] ObjCPropertyDecl=blah:136:38
 // CHECK-PROP-AFTER-METHOD: Punctuation: ")" [136:31 - 136:32] ObjCPropertyDecl=blah:136:38
 // CHECK-PROP-AFTER-METHOD: Identifier: "Foo" [136:33 - 136:36] ObjCClassRef=Foo:1:12
 // CHECK-PROP-AFTER-METHOD: Punctuation: "*" [136:37 - 136:38] ObjCPropertyDecl=blah:136:38

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=127253&r1=127252&r2=127253&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Tue Mar  8 11:10:18 2011
@@ -34,6 +34,7 @@
 #include "clang/Lex/Preprocessor.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "clang/Analysis/Support/SaveAndRestore.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/PrettyStackTrace.h"
@@ -4261,7 +4262,8 @@
   unsigned PreprocessingTokIdx;
   CursorVisitor AnnotateVis;
   SourceManager &SrcMgr;
-
+  bool HasContextSensitiveKeywords;
+  
   bool MoreTokens() const { return TokIdx < NumTokens; }
   unsigned NextToken() const { return TokIdx; }
   void AdvanceToken() { ++TokIdx; }
@@ -4278,7 +4280,8 @@
       AnnotateVis(tu,
                   AnnotateTokensVisitor, this,
                   Decl::MaxPCHLevel, RegionOfInterest),
-      SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()) {}
+      SrcMgr(static_cast<ASTUnit*>(tu->TUData)->getSourceManager()),
+      HasContextSensitiveKeywords(false) { }
 
   void VisitChildren(CXCursor C) { AnnotateVis.VisitChildren(C); }
   enum CXChildVisitResult Visit(CXCursor cursor, CXCursor parent);
@@ -4286,6 +4289,12 @@
   void AnnotateTokens() {
     AnnotateTokens(clang_getTranslationUnitCursor(AnnotateVis.getTU()));
   }
+  
+  /// \brief Determine whether the annotator saw any cursors that have 
+  /// context-sensitive keywords.
+  bool hasContextSensitiveKeywords() const {
+    return HasContextSensitiveKeywords;
+  }
 };
 }
 
@@ -4319,7 +4328,52 @@
   SourceRange cursorRange = getRawCursorExtent(cursor);
   if (cursorRange.isInvalid())
     return CXChildVisit_Recurse;
-        
+      
+  if (!HasContextSensitiveKeywords) {
+    // Objective-C properties can have context-sensitive keywords.
+    if (cursor.kind == CXCursor_ObjCPropertyDecl) {
+      if (ObjCPropertyDecl *Property 
+                  = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(cursor)))
+        HasContextSensitiveKeywords = Property->getPropertyAttributesAsWritten() != 0;
+    }
+    // Objective-C methods can have context-sensitive keywords.
+    else if (cursor.kind == CXCursor_ObjCInstanceMethodDecl ||
+             cursor.kind == CXCursor_ObjCClassMethodDecl) {
+      if (ObjCMethodDecl *Method
+            = dyn_cast_or_null<ObjCMethodDecl>(getCursorDecl(cursor))) {
+        if (Method->getObjCDeclQualifier())
+          HasContextSensitiveKeywords = true;
+        else {
+          for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
+                                           PEnd = Method->param_end();
+               P != PEnd; ++P) {
+            if ((*P)->getObjCDeclQualifier()) {
+              HasContextSensitiveKeywords = true;
+              break;
+            }
+          }
+        }
+      }
+    }    
+    // C++ methods can have context-sensitive keywords.
+    else if (cursor.kind == CXCursor_CXXMethod) {
+      if (CXXMethodDecl *Method
+                  = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(cursor))) {
+        if (Method->hasAttr<FinalAttr>() || Method->hasAttr<OverrideAttr>())
+          HasContextSensitiveKeywords = true;
+      }
+    }
+    // C++ classes can have context-sensitive keywords.
+    else if (cursor.kind == CXCursor_StructDecl ||
+             cursor.kind == CXCursor_ClassDecl ||
+             cursor.kind == CXCursor_ClassTemplate ||
+             cursor.kind == CXCursor_ClassTemplatePartialSpecialization) {
+      if (Decl *D = getCursorDecl(cursor))
+        if (D->hasAttr<FinalAttr>())
+          HasContextSensitiveKeywords = true;
+    }
+  }
+  
   if (clang_isPreprocessing(cursor.kind)) {    
     // For macro instantiations, just note where the beginning of the macro
     // instantiation occurs.
@@ -4607,6 +4661,91 @@
                  GetSafetyThreadStackSize() * 2)) {
     fprintf(stderr, "libclang: crash detected while annotating tokens\n");
   }
+  
+  // If we ran into any entities that involve context-sensitive keywords,
+  // take another pass through the tokens to mark them as such.
+  if (W.hasContextSensitiveKeywords()) {
+    for (unsigned I = 0; I != NumTokens; ++I) {
+      if (clang_getTokenKind(Tokens[I]) != CXToken_Identifier)
+        continue;
+      
+      if (Cursors[I].kind == CXCursor_ObjCPropertyDecl) {
+        IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+        if (ObjCPropertyDecl *Property
+              = dyn_cast_or_null<ObjCPropertyDecl>(getCursorDecl(Cursors[I]))) {
+          if (Property->getPropertyAttributesAsWritten() != 0 &&
+              llvm::StringSwitch<bool>(II->getName())
+                .Case("readonly", true)
+                .Case("assign", true)
+                .Case("readwrite", true)
+                .Case("retain", true)
+                .Case("copy", true)
+                .Case("nonatomic", true)
+                .Case("atomic", true)
+                .Case("getter", true)
+                .Case("setter", true)
+                .Default(false))
+            Tokens[I].int_data[0] = CXToken_Keyword;
+        }
+        continue;
+      }
+      
+      if (Cursors[I].kind == CXCursor_ObjCInstanceMethodDecl ||
+          Cursors[I].kind == CXCursor_ObjCClassMethodDecl) {
+        IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+        if (llvm::StringSwitch<bool>(II->getName())
+              .Case("in", true)
+              .Case("out", true)
+              .Case("inout", true)
+              .Case("oneway", true)
+              .Case("bycopy", true)
+              .Case("byref", true)
+              .Default(false))
+          Tokens[I].int_data[0] = CXToken_Keyword;
+        continue;
+      }
+      
+      if (Cursors[I].kind == CXCursor_CXXMethod) {
+        IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+        if (CXXMethodDecl *Method
+                 = dyn_cast_or_null<CXXMethodDecl>(getCursorDecl(Cursors[I]))) {
+          if ((Method->hasAttr<FinalAttr>() || 
+               Method->hasAttr<OverrideAttr>()) &&
+              Method->getLocation().getRawEncoding() != Tokens[I].int_data[1] &&
+              llvm::StringSwitch<bool>(II->getName())
+                .Case("final", true)
+                .Case("override", true)
+                .Default(false))
+            Tokens[I].int_data[0] = CXToken_Keyword;
+        }
+        continue;
+      }
+      
+      if (Cursors[I].kind == CXCursor_ClassDecl ||
+          Cursors[I].kind == CXCursor_StructDecl ||
+          Cursors[I].kind == CXCursor_ClassTemplate) {
+        IdentifierInfo *II = static_cast<IdentifierInfo *>(Tokens[I].ptr_data);
+        if (II->getName() == "final") {
+          // We have to be careful with 'final', since it could be the name
+          // of a member class rather than the context-sensitive keyword.
+          // So, check whether the cursor associated with this
+          Decl *D = getCursorDecl(Cursors[I]);
+          if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(D)) {
+            if ((Record->hasAttr<FinalAttr>()) &&
+                Record->getIdentifier() != II)
+              Tokens[I].int_data[0] = CXToken_Keyword;
+          } else if (ClassTemplateDecl *ClassTemplate
+                       = dyn_cast_or_null<ClassTemplateDecl>(D)) {
+            CXXRecordDecl *Record = ClassTemplate->getTemplatedDecl();
+            if ((Record->hasAttr<FinalAttr>()) &&
+                Record->getIdentifier() != II)
+              Tokens[I].int_data[0] = CXToken_Keyword;            
+          }
+        }
+        continue;        
+      }
+    }
+  }
 }
 } // end: extern "C"
 





More information about the cfe-commits mailing list