Skip to content

Assertion failure when calling ElaboratedTypeLoc::getTypePtr() #10399

@llvmbot

Description

@llvmbot
Bugzilla Link 10027
Version trunk
OS Linux
Reporter LLVM Bugzilla Contributor
CC @DougGregor

Extended Description

Consider the following source file:
namespace S { typedef int T; }
const S::T x = 5;

A RecursiveASTVisitor with the following method will assert while visiting the declaration of 'x':
bool VisitVarDecl(VarDecl* decl) {
const TypeLoc type_loc = decl->getTypeSourceInfo()->getTypeLoc();
if (const ElaboratedTypeLoc* etype_loc =
dyn_cast(&type_loc)) {
etype_loc->getTypePtr();
}
return true;
}

Here's the relevant part of the stack trace:
#​6 0x0000000001626027 in __assert_fail (
assertion=0x16791a8 "isa(Val) && "cast() argument of incompatible type!"",
file=0x1679170 "include/llvm/Support/Casting.h", line=202,
function=0x167b960 "typename llvm::cast_retty<To, From>::ret_type llvm::cast(const Y&) [with X = clang::ElaboratedType, Y = const clang::Type*]")
#​7 0x0000000000b1ddb5 in llvm::cast<clang::ElaboratedType, clang::Type const*>
(Val=@0x7fffffffc678)
at include/llvm/Support/Casting.h:202
#​8 0x0000000000b1c106 in clang::ConcreteTypeLoc<clang::UnqualTypeLoc, clang::ElaboratedTypeLoc, clang::ElaboratedType, clang::ElaboratedLocInfo>::getTypePtr (
this=0x7fffffffc6b0)
at tools/clang/include/clang/AST/TypeLoc.h:311
#​9 0x0000000000af84f5 in BugReproVisitor::VisitVarDecl (this=0x7ffff6bbfe20,
decl=0x7ffff7f5e450) at repro.cc:22

Here's ElaboratedTypeLoc's getTypePtr(); TypeClass is ElaboratedType and Base is UnqualTypeLoc:
const TypeClass *getTypePtr() const {
return cast(Base::getTypePtr());
}

The problem is that UnqualTypeLoc::getTypePtr() is returning a bogus address, in this case 0x7ffff6c0cfc1 -- note the set low bit, that is, the type that was stored in the TypeSourceInfo is actually a QualType with a const qualifier. Oops. Tracing the source of this bit, apparently we build the VarDecl's TypeSourceInfo from a QualType to which we explicitly add qualifiers (in ConvertDeclSpecToType()).

There are a couple of hacks that could fix the immediate problem, such as changing ElaboratedTypeLoc to inherit from QualifiedTypeLoc instead of UnqualTypeLoc. However, QualifiedTypeLoc does not appear to have gotten much traction in the codebase, and the TypeLoc type hierarchy has some strange behavior (see e.g. UnqualTypeLoc::classof(const TypeLoc*)). Maybe it's time to rip out UnqualTypeLoc and QualifiedTypeLoc, and just deal in QualTypes everywhere.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillac++clang:toolingLibToolingcrashPrefer [crash-on-valid] or [crash-on-invalid]

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions