summaryrefslogtreecommitdiffstats
path: root/clang/lib/Serialization
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-05-01 23:48:14 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-05-01 23:48:14 +0000
commit8d26bb0899dc596067b2caf810f0290ffa1ee2c8 (patch)
treef63a5d0d64ecbd3fe37b2ec53f0abb678db6ba04 /clang/lib/Serialization
parent8fb0d9d24ad0525b689c93b6c51e9c32ff61ac25 (diff)
downloadbcm5719-llvm-8d26bb0899dc596067b2caf810f0290ffa1ee2c8.tar.gz
bcm5719-llvm-8d26bb0899dc596067b2caf810f0290ffa1ee2c8.zip
Add an optional field attached to a DeclRefExpr which points back to the
Decl actually found via name lookup & overload resolution when that Decl is different from the ValueDecl which is actually referenced by the expression. This can be used by AST consumers to correctly attribute references to the spelling location of a using declaration, and otherwise gain insight into the name resolution performed by Clang. The public interface to DRE is kept as narrow as possible: we provide a getFoundDecl() which always returns a NamedDecl, either the ValueDecl referenced or the new, more precise NamedDecl if present. This way AST clients can code against getFoundDecl without know when exactly the AST has a split representation. For an example of the data this provides consider: % cat x.cc namespace N1 { struct S {}; void f(const S&); } void test(N1::S s) { f(s); using N1::f; f(s); } % ./bin/clang -fsyntax-only -Xclang -ast-dump x.cc [...] void test(N1::S s) (CompoundStmt 0x5b02010 <x.cc:5:20, line:9:1> (CallExpr 0x5b01df0 <line:6:3, col:6> 'void' (ImplicitCastExpr 0x5b01dd8 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay> (DeclRefExpr 0x5b01d80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)')) (ImplicitCastExpr 0x5b01e20 <col:5> 'const struct N1::S' lvalue <NoOp> (DeclRefExpr 0x5b01d58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S'))) (DeclStmt 0x5b01ee0 <line:7:3, col:14> 0x5b01e40 "UsingN1::;") (CallExpr 0x5b01fc8 <line:8:3, col:6> 'void' (ImplicitCastExpr 0x5b01fb0 <col:3> 'void (*)(const struct N1::S &)' <FunctionToPointerDecay> (DeclRefExpr 0x5b01f80 <col:3> 'void (const struct N1::S &)' lvalue Function 0x5b01a20 'f' 'void (const struct N1::S &)' (UsingShadow 0x5b01ea0 'f'))) (ImplicitCastExpr 0x5b01ff8 <col:5> 'const struct N1::S' lvalue <NoOp> (DeclRefExpr 0x5b01f58 <col:5> 'N1::S':'struct N1::S' lvalue ParmVar 0x5b01b60 's' 'N1::S':'struct N1::S')))) Now we can tell that the second call is 'using' (no pun intended) the using declaration, and *which* using declaration it sees. Without this, we can mistake calls that go through using declarations for ADL calls, and have no way to attribute names looked up with using declarations to the appropriate UsingDecl. llvm-svn: 130670
Diffstat (limited to 'clang/lib/Serialization')
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp17
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp4
2 files changed, 15 insertions, 6 deletions
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 6b49b7ba6c2..918db7e367c 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -426,6 +426,7 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
E->DeclRefExprBits.HasQualifier = Record[Idx++];
+ E->DeclRefExprBits.HasFoundDecl = Record[Idx++];
E->DeclRefExprBits.HasExplicitTemplateArgs = Record[Idx++];
unsigned NumTemplateArgs = 0;
if (E->hasExplicitTemplateArgs())
@@ -435,6 +436,9 @@ void ASTStmtReader::VisitDeclRefExpr(DeclRefExpr *E) {
E->getInternalQualifierLoc()
= Reader.ReadNestedNameSpecifierLoc(F, Record, Idx);
+ if (E->hasFoundDecl())
+ E->getInternalFoundDecl() = cast<NamedDecl>(Reader.GetDecl(Record[Idx++]));
+
if (E->hasExplicitTemplateArgs())
ReadExplicitTemplateArgumentList(E->getExplicitTemplateArgs(),
NumTemplateArgs);
@@ -1566,12 +1570,13 @@ Stmt *ASTReader::ReadStmtFromStream(PerFileData &F) {
break;
case EXPR_DECL_REF:
- S = DeclRefExpr::CreateEmpty(*Context,
- /*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
- /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1],
- /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 1]
- ? Record[ASTStmtReader::NumExprFields + 2]
- : 0);
+ S = DeclRefExpr::CreateEmpty(
+ *Context,
+ /*HasQualifier=*/Record[ASTStmtReader::NumExprFields],
+ /*HasFoundDecl=*/Record[ASTStmtReader::NumExprFields + 1],
+ /*HasExplicitTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2],
+ /*NumTemplateArgs=*/Record[ASTStmtReader::NumExprFields + 2] ?
+ Record[ASTStmtReader::NumExprFields + 3] : 0);
break;
case EXPR_INTEGER_LITERAL:
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 4fe3bae91a2..bd5889ad929 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -384,6 +384,7 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
VisitExpr(E);
Record.push_back(E->hasQualifier());
+ Record.push_back(E->getDecl() != E->getFoundDecl());
Record.push_back(E->hasExplicitTemplateArgs());
if (E->hasExplicitTemplateArgs()) {
@@ -394,6 +395,9 @@ void ASTStmtWriter::VisitDeclRefExpr(DeclRefExpr *E) {
if (E->hasQualifier())
Writer.AddNestedNameSpecifierLoc(E->getQualifierLoc(), Record);
+ if (E->getDecl() != E->getFoundDecl())
+ Writer.AddDeclRef(E->getFoundDecl(), Record);
+
if (E->hasExplicitTemplateArgs())
AddExplicitTemplateArgumentList(E->getExplicitTemplateArgs());
OpenPOWER on IntegriCloud