r330201 - Move the visitor classes that are used to traverse non-trivial C structs
Akira Hatanaka via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 17 12:05:17 PDT 2018
Author: ahatanak
Date: Tue Apr 17 12:05:17 2018
New Revision: 330201
URL: http://llvm.org/viewvc/llvm-project?rev=330201&view=rev
Log:
Move the visitor classes that are used to traverse non-trivial C structs
to a header file.
This is in preparation for using the visitor classes to warn about
memcpy'ing non-trivial C structs.
See the discussion here:
https://reviews.llvm.org/D45310
rdar://problem/36124208
Added:
cfe/trunk/include/clang/AST/NonTrivialTypeVisitor.h
Modified:
cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp
Added: cfe/trunk/include/clang/AST/NonTrivialTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/NonTrivialTypeVisitor.h?rev=330201&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/NonTrivialTypeVisitor.h (added)
+++ cfe/trunk/include/clang/AST/NonTrivialTypeVisitor.h Tue Apr 17 12:05:17 2018
@@ -0,0 +1,113 @@
+//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the visitor classes that are used to traverse non-trivial
+// structs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+#define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H
+
+#include "clang/AST/Type.h"
+
+namespace clang {
+
+template <class Derived, class RetTy = void> struct DestructedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ return asDerived().visitWithKind(FT.isDestructedType(), FT,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::DestructionKind DK, QualType FT,
+ Ts &&... Args) {
+ switch (DK) {
+ case QualType::DK_objc_strong_lifetime:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_nontrivial_c_struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_none:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_cxx_destructor:
+ return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...);
+ case QualType::DK_objc_weak_lifetime:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown destruction kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, class RetTy = void>
+struct DefaultInitializedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ return asDerived().visitWithKind(
+ FT.isNonTrivialToPrimitiveDefaultInitialize(), FT,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK,
+ QualType FT, Ts &&... Args) {
+ switch (PDIK) {
+ case QualType::PDIK_ARCStrong:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_Struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::PDIK_Trivial:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown default-initialize kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+template <class Derived, bool IsMove, class RetTy = void>
+struct CopiedTypeVisitor {
+ template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
+ QualType::PrimitiveCopyKind PCK =
+ IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove()
+ : FT.isNonTrivialToPrimitiveCopy();
+ return asDerived().visitWithKind(PCK, FT, std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
+ RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ Ts &&... Args) {
+ asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...);
+
+ switch (PCK) {
+ case QualType::PCK_ARCStrong:
+ return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_ARCWeak:
+ return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_Struct:
+ return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_Trivial:
+ return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
+ case QualType::PCK_VolatileTrivial:
+ return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...);
+ }
+
+ llvm_unreachable("unknown primitive copy kind");
+ }
+
+ Derived &asDerived() { return static_cast<Derived &>(*this); }
+};
+
+} // end namespace clang
+
+#endif
Modified: cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp?rev=330201&r1=330200&r2=330201&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGNonTrivialStruct.cpp Tue Apr 17 12:05:17 2018
@@ -14,6 +14,7 @@
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
+#include "clang/AST/NonTrivialTypeVisitor.h"
#include "llvm/Support/ScopedPrinter.h"
#include <array>
@@ -32,101 +33,6 @@ namespace {
enum { DstIdx = 0, SrcIdx = 1 };
const char *ValNameStr[2] = {"dst", "src"};
-template <class Derived, class RetTy = void> struct DestructedTypeVisitor {
- template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
- return asDerived().visit(FT.isDestructedType(), FT,
- std::forward<Ts>(Args)...);
- }
-
- template <class... Ts>
- RetTy visit(QualType::DestructionKind DK, QualType FT, Ts &&... Args) {
- if (asDerived().getContext().getAsArrayType(FT))
- return asDerived().visitArray(DK, FT, std::forward<Ts>(Args)...);
-
- switch (DK) {
- case QualType::DK_objc_strong_lifetime:
- return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
- case QualType::DK_nontrivial_c_struct:
- return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
- case QualType::DK_none:
- return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
- case QualType::DK_cxx_destructor:
- return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...);
- case QualType::DK_objc_weak_lifetime:
- return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
- }
-
- llvm_unreachable("unknown destruction kind");
- }
-
- Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
-template <class Derived, class RetTy = void>
-struct DefaultInitializedTypeVisitor {
- template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
- return asDerived().visit(FT.isNonTrivialToPrimitiveDefaultInitialize(), FT,
- std::forward<Ts>(Args)...);
- }
-
- template <class... Ts>
- RetTy visit(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
- Ts &&... Args) {
- if (asDerived().getContext().getAsArrayType(FT))
- return asDerived().visitArray(PDIK, FT, std::forward<Ts>(Args)...);
-
- switch (PDIK) {
- case QualType::PDIK_ARCStrong:
- return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
- case QualType::PDIK_ARCWeak:
- return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
- case QualType::PDIK_Struct:
- return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
- case QualType::PDIK_Trivial:
- return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
- }
-
- llvm_unreachable("unknown default-initialize kind");
- }
-
- Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
-template <class Derived, bool IsMove, class RetTy = void>
-struct CopiedTypeVisitor {
- template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) {
- QualType::PrimitiveCopyKind PCK =
- IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove()
- : FT.isNonTrivialToPrimitiveCopy();
- return asDerived().visit(PCK, FT, std::forward<Ts>(Args)...);
- }
-
- template <class... Ts>
- RetTy visit(QualType::PrimitiveCopyKind PCK, QualType FT, Ts &&... Args) {
- asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...);
-
- if (asDerived().getContext().getAsArrayType(FT))
- return asDerived().visitArray(PCK, FT, std::forward<Ts>(Args)...);
-
- switch (PCK) {
- case QualType::PCK_ARCStrong:
- return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...);
- case QualType::PCK_ARCWeak:
- return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
- case QualType::PCK_Struct:
- return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
- case QualType::PCK_Trivial:
- return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
- case QualType::PCK_VolatileTrivial:
- return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...);
- }
-
- llvm_unreachable("unknown primitive copy kind");
- }
-
- Derived &asDerived() { return static_cast<Derived &>(*this); }
-};
-
template <class Derived> struct StructVisitor {
StructVisitor(ASTContext &Ctx) : Ctx(Ctx) {}
@@ -172,6 +78,7 @@ template <class Derived, bool IsMove>
struct CopyStructVisitor : StructVisitor<Derived>,
CopiedTypeVisitor<Derived, IsMove> {
using StructVisitor<Derived>::asDerived;
+ using Super = CopiedTypeVisitor<Derived, IsMove>;
CopyStructVisitor(ASTContext &Ctx) : StructVisitor<Derived>(Ctx) {}
@@ -184,6 +91,20 @@ struct CopyStructVisitor : StructVisitor
}
template <class... Ts>
+ void visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffsset,
+ Ts &&... Args) {
+ if (const auto *AT = asDerived().getContext().getAsArrayType(FT)) {
+ asDerived().visitArray(PCK, AT, FT.isVolatileQualified(), FD,
+ CurStructOffsset, std::forward<Ts>(Args)...);
+ return;
+ }
+
+ Super::visitWithKind(PCK, FT, FD, CurStructOffsset,
+ std::forward<Ts>(Args)...);
+ }
+
+ template <class... Ts>
void visitTrivial(QualType FT, const FieldDecl *FD, CharUnits CurStructOffset,
Ts... Args) {
assert(!FT.isVolatileQualified() && "volatile field not expected");
@@ -259,24 +180,24 @@ template <class Derived> struct GenFuncN
}
template <class FieldKind>
- void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
- CharUnits CurStructOffset) {
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
// String for non-volatile trivial fields is emitted when
// flushTrivialFields is called.
if (!FK)
- return asDerived().visitTrivial(QT, FD, CurStructOffset);
+ return asDerived().visitTrivial(QualType(AT, 0), FD, CurStructOffset);
CharUnits FieldOffset = CurStructOffset + asDerived().getFieldOffset(FD);
ASTContext &Ctx = asDerived().getContext();
- const auto *AT = Ctx.getAsConstantArrayType(QT);
- unsigned NumElts = Ctx.getConstantArrayElementCount(AT);
- QualType EltTy = Ctx.getBaseElementType(AT);
+ const ConstantArrayType *CAT = cast<ConstantArrayType>(AT);
+ unsigned NumElts = Ctx.getConstantArrayElementCount(CAT);
+ QualType EltTy = Ctx.getBaseElementType(CAT);
CharUnits EltSize = Ctx.getTypeSizeInChars(EltTy);
appendStr("_AB" + llvm::to_string(FieldOffset.getQuantity()) + "s" +
llvm::to_string(EltSize.getQuantity()) + "n" +
llvm::to_string(NumElts));
- EltTy = QT.isVolatileQualified() ? EltTy.withVolatile() : EltTy;
- asDerived().visit(FK, EltTy, nullptr, FieldOffset);
+ EltTy = IsVolatile ? EltTy.withVolatile() : EltTy;
+ asDerived().visitWithKind(FK, EltTy, nullptr, FieldOffset);
appendStr("_AE");
}
@@ -344,16 +265,36 @@ struct GenBinaryFuncName : CopyStructVis
struct GenDefaultInitializeFuncName
: GenUnaryFuncName<GenDefaultInitializeFuncName>,
DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName> {
+ using Super = DefaultInitializedTypeVisitor<GenDefaultInitializeFuncName>;
GenDefaultInitializeFuncName(CharUnits DstAlignment, ASTContext &Ctx)
: GenUnaryFuncName<GenDefaultInitializeFuncName>("__default_constructor_",
DstAlignment, Ctx) {}
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, FD, CurStructOffset);
+ }
};
struct GenDestructorFuncName : GenUnaryFuncName<GenDestructorFuncName>,
DestructedTypeVisitor<GenDestructorFuncName> {
+ using Super = DestructedTypeVisitor<GenDestructorFuncName>;
GenDestructorFuncName(CharUnits DstAlignment, ASTContext &Ctx)
: GenUnaryFuncName<GenDestructorFuncName>("__destructor_", DstAlignment,
Ctx) {}
+ void visitWithKind(QualType::DestructionKind DK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset);
+ return;
+ }
+
+ Super::visitWithKind(DK, FT, FD, CurStructOffset);
+ }
};
// Helper function that creates CGFunctionInfo for an N-ary special function.
@@ -386,11 +327,13 @@ template <class Derived> struct GenFuncB
}
template <class FieldKind, size_t N>
- void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
- CharUnits CurStackOffset, std::array<Address, N> Addrs) {
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, N> Addrs) {
// Non-volatile trivial fields are copied when flushTrivialFields is called.
if (!FK)
- return asDerived().visitTrivial(QT, FD, CurStackOffset, Addrs);
+ return asDerived().visitTrivial(QualType(AT, 0), FD, CurStackOffset,
+ Addrs);
CodeGenFunction &CGF = *this->CGF;
ASTContext &Ctx = CGF.getContext();
@@ -401,8 +344,7 @@ template <class Derived> struct GenFuncB
for (unsigned I = 0; I < N; ++I)
StartAddrs[I] = getAddrWithOffset(Addrs[I], CurStackOffset, FD);
Address DstAddr = StartAddrs[DstIdx];
- llvm::Value *NumElts =
- CGF.emitArrayLength(Ctx.getAsArrayType(QT), BaseEltQT, DstAddr);
+ llvm::Value *NumElts = CGF.emitArrayLength(AT, BaseEltQT, DstAddr);
unsigned BaseEltSize = Ctx.getTypeSizeInChars(BaseEltQT).getQuantity();
llvm::Value *BaseEltSizeVal =
llvm::ConstantInt::get(NumElts->getType(), BaseEltSize);
@@ -437,7 +379,7 @@ template <class Derived> struct GenFuncB
// Visit the element of the array in the loop body.
CGF.EmitBlock(LoopBB);
- QualType EltQT = Ctx.getAsArrayType(QT)->getElementType();
+ QualType EltQT = AT->getElementType();
CharUnits EltSize = Ctx.getTypeSizeInChars(EltQT);
std::array<Address, N> NewAddrs = Addrs;
@@ -445,8 +387,9 @@ template <class Derived> struct GenFuncB
NewAddrs[I] = Address(
PHIs[I], StartAddrs[I].getAlignment().alignmentAtOffset(EltSize));
- EltQT = QT.isVolatileQualified() ? EltQT.withVolatile() : EltQT;
- this->asDerived().visit(EltQT, nullptr, CharUnits::Zero(), NewAddrs);
+ EltQT = IsVolatile ? EltQT.withVolatile() : EltQT;
+ this->asDerived().visitWithKind(FK, EltQT, nullptr, CharUnits::Zero(),
+ NewAddrs);
LoopBB = CGF.Builder.GetInsertBlock();
@@ -624,7 +567,20 @@ struct GenBinaryFunc : CopyStructVisitor
struct GenDestructor : StructVisitor<GenDestructor>,
GenFuncBase<GenDestructor>,
DestructedTypeVisitor<GenDestructor> {
+ using Super = DestructedTypeVisitor<GenDestructor>;
GenDestructor(ASTContext &Ctx) : StructVisitor<GenDestructor>(Ctx) {}
+
+ void visitWithKind(QualType::DestructionKind DK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset,
+ std::array<Address, 1> Addrs) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(DK, AT, FT.isVolatileQualified(), FD, CurStructOffset, Addrs);
+ return;
+ }
+
+ Super::visitWithKind(DK, FT, FD, CurStructOffset, Addrs);
+ }
+
void visitARCStrong(QualType QT, const FieldDecl *FD,
CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
CGF->destroyARCStrongImprecise(
@@ -648,10 +604,24 @@ struct GenDefaultInitialize
: StructVisitor<GenDefaultInitialize>,
GenFuncBase<GenDefaultInitialize>,
DefaultInitializedTypeVisitor<GenDefaultInitialize> {
+ using Super = DefaultInitializedTypeVisitor<GenDefaultInitialize>;
typedef GenFuncBase<GenDefaultInitialize> GenFuncBaseTy;
+
GenDefaultInitialize(ASTContext &Ctx)
: StructVisitor<GenDefaultInitialize>(Ctx) {}
+ void visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, QualType FT,
+ const FieldDecl *FD, CharUnits CurStructOffset,
+ std::array<Address, 1> Addrs) {
+ if (const auto *AT = getContext().getAsArrayType(FT)) {
+ visitArray(PDIK, AT, FT.isVolatileQualified(), FD, CurStructOffset,
+ Addrs);
+ return;
+ }
+
+ Super::visitWithKind(PDIK, FT, FD, CurStructOffset, Addrs);
+ }
+
void visitARCStrong(QualType QT, const FieldDecl *FD,
CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
CGF->EmitNullInitialization(
@@ -665,17 +635,18 @@ struct GenDefaultInitialize
}
template <class FieldKind, size_t... Is>
- void visitArray(FieldKind FK, QualType QT, const FieldDecl *FD,
- CharUnits CurStackOffset, std::array<Address, 1> Addrs) {
+ void visitArray(FieldKind FK, const ArrayType *AT, bool IsVolatile,
+ const FieldDecl *FD, CharUnits CurStackOffset,
+ std::array<Address, 1> Addrs) {
if (!FK)
- return visitTrivial(QT, FD, CurStackOffset, Addrs);
+ return visitTrivial(QualType(AT, 0), FD, CurStackOffset, Addrs);
ASTContext &Ctx = getContext();
- CharUnits Size = Ctx.getTypeSizeInChars(QT);
- QualType EltTy = Ctx.getBaseElementType(QT);
+ CharUnits Size = Ctx.getTypeSizeInChars(QualType(AT, 0));
+ QualType EltTy = Ctx.getBaseElementType(QualType(AT, 0));
if (Size < CharUnits::fromQuantity(16) || EltTy->getAs<RecordType>()) {
- GenFuncBaseTy::visitArray(FK, QT, FD, CurStackOffset, Addrs);
+ GenFuncBaseTy::visitArray(FK, AT, IsVolatile, FD, CurStackOffset, Addrs);
return;
}
@@ -683,7 +654,7 @@ struct GenDefaultInitialize
Address DstAddr = getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
Address Loc = CGF->Builder.CreateElementBitCast(DstAddr, CGF->Int8Ty);
CGF->Builder.CreateMemSet(Loc, CGF->Builder.getInt8(0), SizeVal,
- QT.isVolatileQualified());
+ IsVolatile);
}
void callSpecialFunction(QualType FT, CharUnits Offset,
More information about the cfe-commits
mailing list