Add libclang support for label statements, gotos, and taking the
address of a label (GNU extension).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113564 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index c899f5d..73e5ce0 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -359,7 +359,7 @@
// Statement visitors
bool VisitStmt(Stmt *S);
bool VisitDeclStmt(DeclStmt *S);
- // FIXME: LabelStmt label?
+ bool VisitGotoStmt(GotoStmt *S);
bool VisitIfStmt(IfStmt *S);
bool VisitSwitchStmt(SwitchStmt *S);
bool VisitCaseStmt(CaseStmt *S);
@@ -377,7 +377,7 @@
bool VisitOffsetOfExpr(OffsetOfExpr *E);
bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
bool VisitMemberExpr(MemberExpr *E);
- // FIXME: AddrLabelExpr (once we have cursors for labels)
+ bool VisitAddrLabelExpr(AddrLabelExpr *E);
bool VisitTypesCompatibleExpr(TypesCompatibleExpr *E);
bool VisitVAArgExpr(VAArgExpr *E);
bool VisitInitListExpr(InitListExpr *E);
@@ -1438,6 +1438,10 @@
return false;
}
+bool CursorVisitor::VisitGotoStmt(GotoStmt *S) {
+ return Visit(MakeCursorLabelRef(S->getLabel(), S->getLabelLoc(), TU));
+}
+
bool CursorVisitor::VisitIfStmt(IfStmt *S) {
if (VarDecl *Var = S->getConditionVariable()) {
if (Visit(MakeCXCursor(Var, TU)))
@@ -1640,6 +1644,10 @@
return VisitExpr(E);
}
+bool CursorVisitor::VisitAddrLabelExpr(AddrLabelExpr *E) {
+ return Visit(MakeCursorLabelRef(E->getLabel(), E->getLabelLoc(), TU));
+}
+
bool CursorVisitor::VisitTypesCompatibleExpr(TypesCompatibleExpr *E) {
return Visit(E->getArgTInfo1()->getTypeLoc()) ||
Visit(E->getArgTInfo2()->getTypeLoc());
@@ -2603,6 +2611,13 @@
return createCXString(Field->getNameAsString());
}
+ case CXCursor_LabelRef: {
+ LabelStmt *Label = getCursorLabelRef(C).first;
+ assert(Label && "Missing label");
+
+ return createCXString(Label->getID()->getName());
+ }
+
default:
return createCXString("<not implemented>");
}
@@ -2615,6 +2630,14 @@
return createCXString("");
}
+ if (clang_isStatement(C.kind)) {
+ Stmt *S = getCursorStmt(C);
+ if (LabelStmt *Label = dyn_cast_or_null<LabelStmt>(S))
+ return createCXString(Label->getID()->getName());
+
+ return createCXString("");
+ }
+
if (C.kind == CXCursor_MacroInstantiation)
return createCXString(getCursorMacroInstantiation(C)->getName()
->getNameStart());
@@ -2687,6 +2710,8 @@
return createCXString("NamespaceRef");
case CXCursor_MemberRef:
return createCXString("MemberRef");
+ case CXCursor_LabelRef:
+ return createCXString("LabelRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
case CXCursor_BlockExpr:
@@ -2701,6 +2726,8 @@
return createCXString("ObjCMessageExpr");
case CXCursor_UnexposedStmt:
return createCXString("UnexposedStmt");
+ case CXCursor_LabelStmt:
+ return createCXString("LabelStmt");
case CXCursor_InvalidFile:
return createCXString("InvalidFile");
case CXCursor_InvalidCode:
@@ -2899,6 +2926,11 @@
return clang_getNullLocation();
}
+ case CXCursor_LabelRef: {
+ std::pair<LabelStmt *, SourceLocation> P = getCursorLabelRef(C);
+ return cxloc::translateSourceLocation(getCursorContext(C), P.second);
+ }
+
default:
// FIXME: Need a way to enumerate all non-reference cases.
llvm_unreachable("Missed a reference kind");
@@ -2909,6 +2941,10 @@
return cxloc::translateSourceLocation(getCursorContext(C),
getLocationFromExpr(getCursorExpr(C)));
+ if (clang_isStatement(C.kind))
+ return cxloc::translateSourceLocation(getCursorContext(C),
+ getCursorStmt(C)->getLocStart());
+
if (C.kind == CXCursor_PreprocessingDirective) {
SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
return cxloc::translateSourceLocation(getCursorContext(C), L);
@@ -2965,6 +3001,9 @@
// FIXME: Figure out what source range to use for a CXBaseSpecifier.
return SourceRange();
+ case CXCursor_LabelRef:
+ return getCursorLabelRef(C).second;
+
default:
// FIXME: Need a way to enumerate all non-reference cases.
llvm_unreachable("Missed a reference kind");
@@ -3017,6 +3056,15 @@
return clang_getNullCursor();
}
+ if (clang_isStatement(C.kind)) {
+ Stmt *S = getCursorStmt(C);
+ if (GotoStmt *Goto = dyn_cast_or_null<GotoStmt>(S))
+ return MakeCXCursor(Goto->getLabel(), getCursorDecl(C),
+ getCursorASTUnit(C));
+
+ return clang_getNullCursor();
+ }
+
if (C.kind == CXCursor_MacroInstantiation) {
if (MacroDefinition *Def = getCursorMacroInstantiation(C)->getDefinition())
return MakeMacroDefinitionCursor(Def, CXXUnit);
@@ -3053,6 +3101,13 @@
CXXUnit));
}
+ case CXCursor_LabelRef:
+ // FIXME: We end up faking the "parent" declaration here because we
+ // don't want to make CXCursor larger.
+ return MakeCXCursor(getCursorLabelRef(C).first,
+ CXXUnit->getASTContext().getTranslationUnitDecl(),
+ CXXUnit);
+
default:
// We would prefer to enumerate all non-reference cursor kinds here.
llvm_unreachable("Unhandled reference cursor kind");
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index 53145a6..6e5f61f 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -65,7 +65,6 @@
case Stmt::CompoundStmtClass:
case Stmt::CaseStmtClass:
case Stmt::DefaultStmtClass:
- case Stmt::LabelStmtClass:
case Stmt::IfStmtClass:
case Stmt::SwitchStmtClass:
case Stmt::WhileStmtClass:
@@ -90,6 +89,10 @@
K = CXCursor_UnexposedStmt;
break;
+ case Stmt::LabelStmtClass:
+ K = CXCursor_LabelStmt;
+ break;
+
case Stmt::PredefinedExprClass:
case Stmt::IntegerLiteralClass:
case Stmt::FloatingLiteralClass:
@@ -153,6 +156,7 @@
case Stmt::BlockExprClass:
K = CXCursor_UnexposedExpr;
break;
+
case Stmt::DeclRefExprClass:
case Stmt::BlockDeclRefExprClass:
// FIXME: UnresolvedLookupExpr?
@@ -357,6 +361,23 @@
return static_cast<MacroInstantiation *>(C.data[0]);
}
+CXCursor cxcursor::MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc,
+ ASTUnit *TU) {
+
+ assert(Label && TU && "Invalid arguments!");
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_LabelRef, { Label, RawLoc, TU } };
+ return C;
+}
+
+std::pair<LabelStmt*, SourceLocation>
+cxcursor::getCursorLabelRef(CXCursor C) {
+ assert(C.kind == CXCursor_LabelRef);
+ return std::make_pair(static_cast<LabelStmt *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
return (Decl *)Cursor.data[0];
}
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index eff71f3..743b38b 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -27,6 +27,7 @@
class Decl;
class Expr;
class FieldDecl;
+class LabelStmt;
class MacroDefinition;
class MacroInstantiation;
class NamedDecl;
@@ -128,6 +129,13 @@
/// source range.
MacroInstantiation *getCursorMacroInstantiation(CXCursor C);
+/// \brief Create a label reference at the given location.
+CXCursor MakeCursorLabelRef(LabelStmt *Label, SourceLocation Loc, ASTUnit *TU);
+
+/// \brief Unpack a label reference into the label statement it refers to and
+/// the location of the reference.
+std::pair<LabelStmt *, SourceLocation> getCursorLabelRef(CXCursor C);
+
Decl *getCursorDecl(CXCursor Cursor);
Expr *getCursorExpr(CXCursor Cursor);
Stmt *getCursorStmt(CXCursor Cursor);