Skip to content

Commit

Permalink
Skip non-dep typedefs in replace-dependent-typedef
Browse files Browse the repository at this point in the history
Only consider typedefs that depend on other typedefs in
replace-dependent-typedef.

This prevents the pass from reporting a success when no actual
change has been made, like in the case when a typedef belongs to
and refers to a template struct (where multiple possible string
representations may confuse the checks).

This fixes csmith-project#279.
  • Loading branch information
emaxx-google committed Jan 14, 2025
1 parent 31e855e commit d0f4d96
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
1 change: 1 addition & 0 deletions clang_delta/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@ EXTRA_DIST = \
tests/rename-fun/test1.h \
tests/rename-param/invalid.c \
tests/rename-var/rename-var.c \
tests/replace-dependent-typedef/test2.cc \
tests/replace-derived-class/replace-derived1.cpp \
tests/replace-derived-class/replace-derived2.cpp \
tests/replace-derived-class/replace-derived3.cpp \
Expand Down
1 change: 1 addition & 0 deletions clang_delta/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,7 @@ EXTRA_DIST = \
tests/rename-fun/test1.h \
tests/rename-param/invalid.c \
tests/rename-var/rename-var.c \
tests/replace-dependent-typedef/test2.cc \
tests/replace-derived-class/replace-derived1.cpp \
tests/replace-derived-class/replace-derived2.cpp \
tests/replace-derived-class/replace-derived3.cpp \
Expand Down
49 changes: 49 additions & 0 deletions clang_delta/ReplaceDependentTypedef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,53 @@ It also tries to reduce the typedef chain, e.g. \n\
static RegisterTransformation<ReplaceDependentTypedef>
Trans("replace-dependent-typedef", DescriptionMsg);

namespace {

bool DependsOnTypedef(const Type &Ty) {
switch (Ty.getTypeClass()) {
case Type::SubstTemplateTypeParm: {
const SubstTemplateTypeParmType *TP =
dyn_cast<SubstTemplateTypeParmType>(&Ty);
const Type *ReplTy = TP->getReplacementType().getTypePtr();
return DependsOnTypedef(*ReplTy);
}

case Type::Elaborated: {
const ElaboratedType *ETy = dyn_cast<ElaboratedType>(&Ty);
const Type *NamedTy = ETy->getNamedType().getTypePtr();
return DependsOnTypedef(*NamedTy);
}

case Type::Typedef: {
return true;
}

case Type::DependentName: {
const DependentNameType *DNT = dyn_cast<DependentNameType>(&Ty);
const NestedNameSpecifier *Specifier = DNT->getQualifier();
if (!Specifier)
return false;
const Type *NestedTy = Specifier->getAsType();
if (!NestedTy)
return false;
return DependsOnTypedef(*NestedTy);
}

case Type::Record:
case Type::Builtin: { // fall-through
return false;
}

default:
return false;
}

TransAssert(0 && "Unreachable code!");
return false;
}

} // namespace

class ReplaceDependentTypedefCollectionVisitor : public
RecursiveASTVisitor<ReplaceDependentTypedefCollectionVisitor> {

Expand Down Expand Up @@ -137,6 +184,8 @@ void ReplaceDependentTypedef::handleOneTypedefDecl(const TypedefDecl *D)

if (!isValidType(D->getUnderlyingType()))
return;
if (!DependsOnTypedef(*D->getUnderlyingType()))
return;

std::string Str = "";
bool Typename = false;
Expand Down
10 changes: 10 additions & 0 deletions clang_delta/tests/replace-dependent-typedef/test2.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %clang_delta --query-instances=replace-dependent-typedef %s 2>&1 | %remove_lit_checks | FileCheck %s

template <typename T>
struct D {
struct Inner;
// This shouldn't be treated as an instance:
typedef D::Inner Bar;
};

// CHECK: Available transformation instances: 0

0 comments on commit d0f4d96

Please sign in to comment.