Index: test/Index/annotate-tokens.cpp =================================================================== --- test/Index/annotate-tokens.cpp +++ test/Index/annotate-tokens.cpp @@ -34,13 +34,15 @@ } class C { - ~C(); -}; - -// RUN: c-index-test -test-annotate-tokens=%s:1:1:38:1 %s -fno-delayed-template-parsing | FileCheck %s -// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition) -// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition) -// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition) + ~C(); +}; + +auto test5(X) -> X; + +// RUN: c-index-test -test-annotate-tokens=%s:1:1:41:1 %s -std=c++14 -fno-delayed-template-parsing | FileCheck %s +// CHECK: Keyword: "struct" [1:1 - 1:7] StructDecl=bonk:1:8 (Definition) +// CHECK: Identifier: "bonk" [1:8 - 1:12] StructDecl=bonk:1:8 (Definition) +// CHECK: Punctuation: "{" [1:13 - 1:14] StructDecl=bonk:1:8 (Definition) // CHECK: Punctuation: "}" [1:15 - 1:16] StructDecl=bonk:1:8 (Definition) // CHECK: Punctuation: ";" [1:16 - 1:17] // CHECK: Keyword: "void" [2:1 - 2:5] FunctionDecl=test:2:6 (Definition) @@ -181,12 +183,20 @@ // CHECK: Punctuation: "(" [29:18 - 29:19] CXXMethod=foo:29:15 (Definition) // CHECK: Punctuation: ")" [29:19 - 29:20] CXXMethod=foo:29:15 (Definition) // CHECK: Punctuation: "{" [29:21 - 29:22] CompoundStmt= -// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt= -// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3 -// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3 - -// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2 -// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt= +// CHECK: Punctuation: "}" [29:22 - 29:23] CompoundStmt= +// CHECK: Punctuation: "~" [37:3 - 37:4] CXXDestructor=~C:37:3 +// CHECK: Identifier: "C" [37:4 - 37:5] CXXDestructor=~C:37:3 +// CHECK: Keyword: "auto" [40:1 - 40:5] FunctionDecl=test5:40:6 +// CHECK: Identifier: "test5" [40:6 - 40:11] FunctionDecl=test5:40:6 +// CHECK: Punctuation: "(" [40:11 - 40:12] FunctionDecl=test5:40:6 +// CHECK: Identifier: "X" [40:12 - 40:13] TypeRef=struct X:7:8 +// CHECK: Punctuation: ")" [40:13 - 40:14] FunctionDecl=test5:40:6 +// CHECK: Punctuation: "->" [40:15 - 40:17] FunctionDecl=test5:40:6 +// CHECK: Identifier: "X" [40:18 - 40:19] TypeRef=struct X:7:8 +// CHECK: Punctuation: ";" [40:19 - 40:20] + +// RUN: env LIBCLANG_DISABLE_CRASH_RECOVERY=1 c-index-test -test-annotate-tokens=%s:32:1:32:13 %s | FileCheck %s -check-prefix=CHECK2 +// CHECK2: Keyword: "if" [32:3 - 32:5] IfStmt= // CHECK2: Punctuation: "(" [32:6 - 32:7] IfStmt= // CHECK2: Keyword: "int" [32:7 - 32:10] VarDecl=p:32:11 (Definition) // CHECK2: Identifier: "p" [32:11 - 32:12] VarDecl=p:32:11 (Definition) Index: tools/libclang/CIndex.cpp =================================================================== --- tools/libclang/CIndex.cpp +++ tools/libclang/CIndex.cpp @@ -782,12 +782,22 @@ if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; - return false; -} - -/// \brief Compare two base or member initializers based on their source order. -static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X, - CXXCtorInitializer *const *Y) { + return false; +} + +static bool HasTrailingReturnType(FunctionDecl *ND) { + const QualType Ty = ND->getType(); + if (const FunctionType *AFT = Ty->getAs()) { + if (const FunctionProtoType *FT = dyn_cast(AFT)) + return FT->hasTrailingReturn(); + } + + return false; +} + +/// \brief Compare two base or member initializers based on their source order. +static int CompareCXXCtorInitializers(CXXCtorInitializer *const *X, + CXXCtorInitializer *const *Y) { return (*X)->getSourceOrder() - (*Y)->getSourceOrder(); } @@ -801,20 +811,22 @@ if (TypeSourceInfo *TSInfo = ND->getTypeSourceInfo()) { // Visit the function declaration's syntactic components in the order - // written. This requires a bit of work. - TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); - FunctionTypeLoc FTL = TL.getAs(); - - // If we have a function declared directly (without the use of a typedef), - // visit just the return type. Otherwise, just visit the function's type - // now. - if ((FTL && !isa(ND) && Visit(FTL.getReturnLoc())) || - (!FTL && Visit(TL))) - return true; - - // Visit the nested-name-specifier, if present. - if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc()) - if (VisitNestedNameSpecifierLoc(QualifierLoc)) + // written. This requires a bit of work. + TypeLoc TL = TSInfo->getTypeLoc().IgnoreParens(); + FunctionTypeLoc FTL = TL.getAs(); + const bool HasTrailingRT = HasTrailingReturnType(ND); + + // If we have a function declared directly (without the use of a typedef), + // visit just the return type. Otherwise, just visit the function's type + // now. + if ((FTL && !isa(ND) && !HasTrailingRT && + Visit(FTL.getReturnLoc())) || + (!FTL && Visit(TL))) + return true; + + // Visit the nested-name-specifier, if present. + if (NestedNameSpecifierLoc QualifierLoc = ND->getQualifierLoc()) + if (VisitNestedNameSpecifierLoc(QualifierLoc)) return true; // Visit the declaration name. @@ -824,13 +836,17 @@ // FIXME: Visit explicitly-specified template arguments! - // Visit the function parameters, if we have a function type. - if (FTL && VisitFunctionTypeLoc(FTL, true)) - return true; - - // FIXME: Attributes? - } - + // Visit the function parameters, if we have a function type. + if (FTL && VisitFunctionTypeLoc(FTL, true)) + return true; + + // Visit the function's trailing return type. + if (FTL && HasTrailingRT && Visit(FTL.getReturnLoc())) + return true; + + // FIXME: Attributes? + } + if (ND->doesThisDeclarationHaveABody() && !ND->isLateTemplateParsed()) { if (CXXConstructorDecl *Constructor = dyn_cast(ND)) { // Find the initializers that were written in the source.