[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