[Sema] Fix location of star ('*') inside MemberPointerTypeLoc

Summary: Copy of https://reviews.llvm.org/D72073?id=235842, submitting with ilya-biryukov's permission.

Reviewers: gribozavr, gribozavr2

Reviewed By: gribozavr2

Subscribers: mgorny, gribozavr2, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D76061
This commit is contained in:
Marcel Hlopko 2020-03-13 10:47:37 +01:00 committed by Dmitri Gribenko
parent db1f40d1a1
commit ce79c42469
5 changed files with 31 additions and 7 deletions

View File

@ -1518,6 +1518,8 @@ struct DeclaratorChunk {
struct MemberPointerTypeInfo {
/// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic.
unsigned TypeQuals : 5;
/// Location of the '*' token.
unsigned StarLoc;
// CXXScopeSpec has a constructor, so it can't be a direct member.
// So we need some pointer-aligned storage and a bit of trickery.
alignas(CXXScopeSpec) char ScopeMem[sizeof(CXXScopeSpec)];
@ -1660,11 +1662,13 @@ struct DeclaratorChunk {
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
unsigned TypeQuals,
SourceLocation Loc) {
SourceLocation StarLoc,
SourceLocation EndLoc) {
DeclaratorChunk I;
I.Kind = MemberPointer;
I.Loc = SS.getBeginLoc();
I.EndLoc = Loc;
I.EndLoc = EndLoc;
I.Mem.StarLoc = StarLoc.getRawEncoding();
I.Mem.TypeQuals = TypeQuals;
new (I.Mem.ScopeMem) CXXScopeSpec(SS);
return I;

View File

@ -5643,8 +5643,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
return;
}
SourceLocation Loc = ConsumeToken();
D.SetRangeEnd(Loc);
SourceLocation StarLoc = ConsumeToken();
D.SetRangeEnd(StarLoc);
DeclSpec DS(AttrFactory);
ParseTypeQualifierListOpt(DS);
D.ExtendWithDeclSpec(DS);
@ -5655,7 +5655,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
// Sema will have to catch (syntactically invalid) pointers into global
// scope. It has to catch pointers into namespace scope anyway.
D.AddTypeInfo(DeclaratorChunk::getMemberPointer(
SS, DS.getTypeQualifiers(), DS.getEndLoc()),
SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),
std::move(DS.getAttributes()),
/* Don't replace range end. */ SourceLocation());
return;

View File

@ -5840,7 +5840,7 @@ namespace {
}
// Finally fill in MemberPointerLocInfo fields.
TL.setStarLoc(Chunk.Loc);
TL.setStarLoc(SourceLocation::getFromRawEncoding(Chunk.Mem.StarLoc));
TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {

View File

@ -42,4 +42,5 @@ clang_target_link_libraries(ASTTests
clangFrontend
clangSerialization
clangTooling
LLVMTestingSupport
)

View File

@ -15,11 +15,12 @@
//
//===----------------------------------------------------------------------===//
#include "clang/AST/ASTContext.h"
#include "MatchVerifier.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Testing/Support/Annotations.h"
#include "gtest/gtest.h"
namespace clang {
@ -842,5 +843,23 @@ TEST(FunctionDecl, ExceptionSpecifications) {
Language::Lang_CXX11));
}
TEST(Decl, MemberPointerStarLoc) {
llvm::Annotations Example(R"cpp(
struct X {};
int X::$star^* a;
)cpp");
auto AST = tooling::buildASTFromCode(Example.code());
SourceManager &SM = AST->getSourceManager();
auto &Ctx = AST->getASTContext();
auto *VD = selectFirst<VarDecl>("vd", match(varDecl().bind("vd"), Ctx));
ASSERT_TRUE(VD != nullptr);
auto TL =
VD->getTypeSourceInfo()->getTypeLoc().castAs<MemberPointerTypeLoc>();
ASSERT_EQ(SM.getFileOffset(TL.getStarLoc()), Example.point("star"));
}
} // end namespace ast_matchers
} // end namespace clang