Author: Fangrui Song Date: 2022-04-08T18:37:26-07:00 New Revision: a58d0af058038595c93de961b725f86997cf8d4a
URL: https://github.com/llvm/llvm-project/commit/a58d0af058038595c93de961b725f86997cf8d4a DIFF: https://github.com/llvm/llvm-project/commit/a58d0af058038595c93de961b725f86997cf8d4a.diff LOG: Revert D121556 "[randstruct] Add randomize structure layout support" This reverts commit 3f0587d0c668202bb89d29a25432aa290e551a31. Not all tests pass after a few rounds of fixes. I spot one failure that std::shuffle (potentially different results with different STL implementations) was misused and replaced it with llvm::shuffle, but there appears to be another failure in a Windows build. The latest failure is reported on https://reviews.llvm.org/D121556#3440383 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/AST/Decl.h clang/include/clang/AST/DeclBase.h clang/include/clang/Basic/Attr.td clang/include/clang/Basic/AttrDocs.td clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Basic/LangOptions.h clang/include/clang/Driver/Options.td clang/lib/AST/CMakeLists.txt clang/lib/AST/Decl.cpp clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Sema/SemaCast.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaDeclAttr.cpp clang/test/Misc/pragma-attribute-supported-attributes-list.test clang/unittests/AST/CMakeLists.txt llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn Removed: clang/include/clang/AST/Randstruct.h clang/lib/AST/Randstruct.cpp clang/unittests/AST/RandstructTest.cpp ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f4feaeabf3548..7e8537e890714 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -54,20 +54,6 @@ Major New Features There is an analogous ``zero_call_used_regs`` attribute to allow for finer control of this feature. -- Clang now supports randomizing structure layout in C. This feature is a - compile-time hardening technique, making it more diff icult for an attacker to - retrieve data from structures. Specify randomization with the - ``randomize_layout`` attribute. The corresponding ``no_randomize_layout`` - attribute can be used to turn the feature off. - - A seed value is required to enable randomization, and is deterministic based - on a seed value. Use the ``-frandomize-layout-seed=`` or - ``-frandomize-layout-seed-file=`` flags. - - .. note:: - - Randomizing structure layout is a C-only feature. - Bug Fixes ------------------ - ``CXXNewExpr::getArraySize()`` previously returned a ``llvm::Optional`` diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 21a8545920387..1246287ee2e62 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4051,12 +4051,6 @@ class RecordDecl : public TagDecl { RecordDeclBits.ParamDestroyedInCallee = V; } - bool isRandomized() const { return RecordDeclBits.IsRandomized; } - - void setIsRandomized(bool V) { RecordDeclBits.IsRandomized = V; } - - void reorderFields(const SmallVectorImpl<Decl *> &Fields); - /// Determines whether this declaration represents the /// injected class name. /// diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index a4a44e0b30e64..a89f776248c1f 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -313,7 +313,6 @@ class alignas(8) Decl { friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; - friend class RecordDecl; template<typename decl_type> friend class Redeclarable; /// Access - Used by C++ decls for the access specifier. @@ -1541,13 +1540,10 @@ class DeclContext { /// Represents the way this type is passed to a function. uint64_t ArgPassingRestrictions : 2; - - /// Indicates whether this struct has had its field layout randomized. - uint64_t IsRandomized : 1; }; /// Number of non-inherited bits in RecordDeclBitfields. - enum { NumRecordDeclBits = 15 }; + enum { NumRecordDeclBits = 14 }; /// Stores the bits used by OMPDeclareReductionDecl. /// If modified NumOMPDeclareReductionDeclBits and the accessor diff --git a/clang/include/clang/AST/Randstruct.h b/clang/include/clang/AST/Randstruct.h deleted file mode 100644 index 0110e8c355551..0000000000000 --- a/clang/include/clang/AST/Randstruct.h +++ /dev/null @@ -1,38 +0,0 @@ -//===- Randstruct.h - Interfact for structure randomization -------*- C++ -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the interface for Clang's structure field layout -// randomization. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_RANDSTRUCT_H -#define LLVM_CLANG_AST_RANDSTRUCT_H - -namespace llvm { -template <typename T> class ArrayRef; -template <typename T> class SmallVectorImpl; -class StringRef; -} // end namespace llvm - -namespace clang { - -class ASTContext; -class Decl; -class RecordDecl; - -namespace randstruct { - -bool randomizeStructureLayout(const ASTContext &Context, llvm::StringRef Name, - llvm::ArrayRef<Decl *> Fields, - llvm::SmallVectorImpl<Decl *> &FinalOrdering); - -} // namespace randstruct -} // namespace clang - -#endif // LLVM_CLANG_AST_RANDSTRUCT_H diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index dee9ede951745..c7141ff463b38 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3957,18 +3957,3 @@ def HLSLNumThreads: InheritableAttr { let LangOpts = [HLSL]; let Documentation = [NumThreadsDocs]; } - -def RandomizeLayout : InheritableAttr { - let Spellings = [GCC<"randomize_layout">]; - let Subjects = SubjectList<[Record]>; - let Documentation = [ClangRandomizeLayoutDocs]; - let LangOpts = [COnly]; -} - -def NoRandomizeLayout : InheritableAttr { - let Spellings = [GCC<"no_randomize_layout">]; - let Subjects = SubjectList<[Record]>; - let Documentation = [ClangRandomizeLayoutDocs]; - let LangOpts = [COnly]; -} -def : MutualExclusions<[RandomizeLayout, NoRandomizeLayout]>; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 6a8b2e600f949..89db454f7dac4 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -6379,35 +6379,3 @@ dictate the thread id. Total number of threads executed is ``X * Y * Z``. The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-numthreads }]; } - -def ClangRandomizeLayoutDocs : Documentation { - let Category = DocCatDecl; - let Heading = "randomize_layout, no_randomize_layout"; - let Content = [{ -The attribute ``randomize_layout``, when attached to a C structure, selects it -for structure layout field randomization; a compile-time hardening technique. A -"seed" value, is specified via the ``-frandomize-layout-seed=`` command line flag. -For example: - -.. code-block:: bash - - SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'` - make ... CFLAGS="-frandomize-layout-seed=$SEED" ... - -You can also supply the seed in a file with ``-frandomize-layout-seed-file=``. -For example: - -.. code-block:: bash - - od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n' > /tmp/seed_file.txt - make ... CFLAGS="-frandomize-layout-seed-file=/tmp/seed_file.txt" ... - -The randomization is deterministic based for a given seed, so the entire -program should be compiled with the same seed, but keep the seed safe -otherwise. - -The attribute ``no_randomize_layout``, when attached to a C structure, -instructs the compiler that this structure should not have its field layout -randomized. - }]; -} diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 1100f775ed6ab..89260a5f4b47d 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -165,8 +165,6 @@ def err_drv_amdgpu_ieee_without_no_honor_nans : Error< "invalid argument '-mno-amdgpu-ieee' only allowed with relaxed NaN handling">; def err_drv_argument_not_allowed_with : Error< "invalid argument '%0' not allowed with '%1'">; -def err_drv_cannot_open_randomize_layout_seed_file : Error< - "cannot read randomize layout seed file '%0'">; def err_drv_invalid_version_number : Error< "invalid version number in '%0'">; def err_drv_no_linker_llvm_support : Error< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3213163ee7876..d8fd33deae115 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11588,7 +11588,5 @@ def err_hlsl_numthreads_argument_oor : Error<"argument '%select{X|Y|Z}0' to numt def err_hlsl_numthreads_invalid : Error<"total number of threads cannot exceed %0">; def err_hlsl_attribute_param_mismatch : Error<"%0 attribute parameters do not match the previous declaration">; -// Layout randomization warning. -def err_cast_from_randomized_struct : Error< - "casting from randomized structure pointer type %0 to %1">; } // end of sema component. + diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index f82992877c0b4..f5a2fd8461674 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -445,9 +445,6 @@ class LangOptions : public LangOptionsBase { /// The default stream kind used for HIP kernel launching. GPUDefaultStreamKind GPUDefaultStream; - /// The seed used by the randomize structure layout feature. - std::string RandstructSeed; - LangOptions(); // Define accessors/mutators for language options of enumeration type. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 98443b2757c93..799fd1b62f185 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2122,12 +2122,6 @@ defm merge_all_constants : BoolFOption<"merge-all-constants", def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Format message diagnostics so that they fit within N columns">, MarshallingInfoInt<DiagnosticOpts<"MessageLength">>; -def frandomize_layout_seed_EQ : Joined<["-"], "frandomize-layout-seed=">, - MetaVarName<"<seed>">, Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"The seed used by the randomize structure layout feature">; -def frandomize_layout_seed_file_EQ : Joined<["-"], "frandomize-layout-seed-file=">, - MetaVarName<"<file>">, Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"File holding the seed used by the randomize structure layout feature">; def fms_compatibility : Flag<["-"], "fms-compatibility">, Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Enable full Microsoft Visual C++ compatibility">, MarshallingInfoFlag<LangOpts<"MSVCCompat">>; diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 24c8cb89c7ff6..9365a2272b3e7 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -97,7 +97,6 @@ add_clang_library(clangAST ParentMap.cpp PrintfFormatString.cpp QualTypeNames.cpp - Randstruct.cpp RawCommentList.cpp RecordLayout.cpp RecordLayoutBuilder.cpp diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index c651fa22a0351..6af7a37dfc7b2 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -30,7 +30,6 @@ #include "clang/AST/ODRHash.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/PrettyPrinter.h" -#include "clang/AST/Randstruct.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateBase.h" @@ -4584,7 +4583,6 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, setHasNonTrivialToPrimitiveCopyCUnion(false); setParamDestroyedInCallee(false); setArgPassingRestrictions(APK_CanPassInRegs); - setIsRandomized(false); } RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, @@ -4668,12 +4666,6 @@ bool RecordDecl::isMsStruct(const ASTContext &C) const { return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1; } -void RecordDecl::reorderFields(const SmallVectorImpl<Decl *> &Fields) { - std::tie(FirstDecl, LastDecl) = DeclContext::BuildDeclChain(Fields, false); - LastDecl->NextInContextAndBits.setPointer(nullptr); - setIsRandomized(true); -} - void RecordDecl::LoadFieldsFromExternalStorage() const { ExternalASTSource *Source = getASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); diff --git a/clang/lib/AST/Randstruct.cpp b/clang/lib/AST/Randstruct.cpp deleted file mode 100644 index 477915eade547..0000000000000 --- a/clang/lib/AST/Randstruct.cpp +++ /dev/null @@ -1,223 +0,0 @@ -//===--- Randstruct.cpp ---------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains the implementation for Clang's structure field layout -// randomization. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/Randstruct.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTDiagnostic.h" -#include "clang/AST/Attr.h" -#include "clang/Basic/Diagnostic.h" -#include "llvm/ADT/SmallVector.h" - -#include <algorithm> -#include <random> -#include <set> -#include <sstream> -#include <string> - -using clang::ASTContext; -using clang::FieldDecl; -using llvm::SmallVector; - -namespace { - -// FIXME: Replace this with some discovery once that mechanism exists. -enum { CACHE_LINE = 64 }; - -// The Bucket class holds the struct fields we're trying to fill to a -// cache-line. -class Bucket { - SmallVector<FieldDecl *, 64> Fields; - int Size = 0; - -public: - virtual ~Bucket() = default; - - SmallVector<FieldDecl *, 64> &fields() { return Fields; } - void addField(FieldDecl *Field, int FieldSize); - virtual bool canFit(int FieldSize) const { - return Size + FieldSize <= CACHE_LINE; - } - virtual bool isBitfieldRun() const { return false; } - bool full() const { return Size >= CACHE_LINE; } -}; - -void Bucket::addField(FieldDecl *Field, int FieldSize) { - Size += FieldSize; - Fields.push_back(Field); -} - -struct BitfieldRunBucket : public Bucket { - bool canFit(int FieldSize) const override { return true; } - bool isBitfieldRun() const override { return true; } -}; - -void randomizeStructureLayoutImpl(const ASTContext &Context, - llvm::SmallVectorImpl<FieldDecl *> &FieldsOut, - std::mt19937 &RNG) { - // All of the Buckets produced by best-effort cache-line algorithm. - SmallVector<std::unique_ptr<Bucket>, 16> Buckets; - - // The current bucket of fields that we are trying to fill to a cache-line. - std::unique_ptr<Bucket> CurrentBucket; - - // The current bucket containing the run of adjacent bitfields to ensure they - // remain adjacent. - std::unique_ptr<BitfieldRunBucket> CurrentBitfieldRun; - - // Tracks the number of fields that we failed to fit to the current bucket, - // and thus still need to be added later. - size_t Skipped = 0; - - while (!FieldsOut.empty()) { - // If we've Skipped more fields than we have remaining to place, that means - // that they can't fit in our current bucket, and we need to start a new - // one. - if (Skipped >= FieldsOut.size()) { - Skipped = 0; - Buckets.push_back(std::move(CurrentBucket)); - } - - // Take the first field that needs to be put in a bucket. - auto FieldIter = FieldsOut.begin(); - FieldDecl *FD = *FieldIter; - - if (FD->isBitField() && !FD->isZeroLengthBitField(Context)) { - // Start a bitfield run if this is the first bitfield we have found. - if (!CurrentBitfieldRun) - CurrentBitfieldRun = std::make_unique<BitfieldRunBucket>(); - - // We've placed the field, and can remove it from the "awaiting Buckets" - // vector called "Fields." - CurrentBitfieldRun->addField(FD, /*FieldSize is irrelevant here*/ 1); - FieldsOut.erase(FieldIter); - continue; - } - - // Else, current field is not a bitfield. If we were previously in a - // bitfield run, end it. - if (CurrentBitfieldRun) - Buckets.push_back(std::move(CurrentBitfieldRun)); - - // If we don't have a bucket, make one. - if (!CurrentBucket) - CurrentBucket = std::make_unique<Bucket>(); - - uint64_t Width = Context.getTypeInfo(FD->getType()).Width; - if (Width >= CACHE_LINE) { - std::unique_ptr<Bucket> OverSized = std::make_unique<Bucket>(); - OverSized->addField(FD, Width); - FieldsOut.erase(FieldIter); - Buckets.push_back(std::move(OverSized)); - continue; - } - - // If it fits, add it. - if (CurrentBucket->canFit(Width)) { - CurrentBucket->addField(FD, Width); - FieldsOut.erase(FieldIter); - - // If it's now full, tie off the bucket. - if (CurrentBucket->full()) { - Skipped = 0; - Buckets.push_back(std::move(CurrentBucket)); - } - } else { - // We can't fit it in our current bucket. Move to the end for processing - // later. - ++Skipped; // Mark it skipped. - FieldsOut.push_back(FD); - FieldsOut.erase(FieldIter); - } - } - - // Done processing the fields awaiting a bucket. - - // If we were filling a bucket, tie it off. - if (CurrentBucket) - Buckets.push_back(std::move(CurrentBucket)); - - // If we were processing a bitfield run bucket, tie it off. - if (CurrentBitfieldRun) - Buckets.push_back(std::move(CurrentBitfieldRun)); - - llvm::shuffle(std::begin(Buckets), std::end(Buckets), RNG); - - // Produce the new ordering of the elements from the Buckets. - SmallVector<FieldDecl *, 16> FinalOrder; - for (const std::unique_ptr<Bucket> &B : Buckets) { - llvm::SmallVectorImpl<FieldDecl *> &RandFields = B->fields(); - if (!B->isBitfieldRun()) - llvm::shuffle(std::begin(RandFields), std::end(RandFields), RNG); - - FinalOrder.insert(FinalOrder.end(), RandFields.begin(), RandFields.end()); - } - - FieldsOut = FinalOrder; -} - -} // anonymous namespace - -namespace clang { -namespace randstruct { - -bool randomizeStructureLayout(const ASTContext &Context, StringRef Name, - ArrayRef<Decl *> Fields, - SmallVectorImpl<Decl *> &FinalOrdering) { - SmallVector<FieldDecl *, 64> RandomizedFields; - - unsigned TotalNumFields = 0; - for (Decl *D : Fields) { - ++TotalNumFields; - if (auto *FD = dyn_cast<FieldDecl>(D)) - RandomizedFields.push_back(FD); - else - FinalOrdering.push_back(D); - } - - if (RandomizedFields.empty()) - return false; - - // Struct might end with a variable-length array or an array of size 0 or 1, - // in which case we don't want to randomize it. - FieldDecl *VLA = nullptr; - const auto *CA = - dyn_cast<ConstantArrayType>(RandomizedFields.back()->getType()); - if ((CA && (CA->getSize().sle(2) || CA->isIncompleteArrayType())) || - llvm::any_of(Fields, [](Decl *D) { - if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) { - const Type *FDTy = FD->getType().getTypePtr(); - if (const RecordType *FDTTy = FDTy->getAs<RecordType>()) - return FDTTy->getDecl()->hasFlexibleArrayMember(); - } - return false; - })) - VLA = RandomizedFields.pop_back_val(); - - std::string Seed = (Context.getLangOpts().RandstructSeed + Name).str(); - std::seed_seq SeedSeq(Seed.begin(), Seed.end()); - std::mt19937 RNG(SeedSeq); - - randomizeStructureLayoutImpl(Context, RandomizedFields, RNG); - if (VLA) - RandomizedFields.push_back(VLA); - - FinalOrdering.insert(FinalOrdering.end(), RandomizedFields.begin(), - RandomizedFields.end()); - - assert(TotalNumFields == FinalOrdering.size() && - "Decl count has been altered after Randstruct randomization!"); - return true; -} - -} // end namespace randstruct -} // end namespace clang diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 1601dba171d26..baac938412ec8 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5907,14 +5907,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString("-fmessage-length=" + Twine(MessageLength))); - if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_EQ)) - CmdArgs.push_back( - Args.MakeArgString("-frandomize-layout-seed=" + Twine(A->getValue(0)))); - - if (Arg *A = Args.getLastArg(options::OPT_frandomize_layout_seed_file_EQ)) - CmdArgs.push_back(Args.MakeArgString("-frandomize-layout-seed-file=" + - Twine(A->getValue(0)))); - // -fvisibility= and -fvisibility-ms-compat are of a piece. if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ, options::OPT_fvisibility_ms_compat)) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 5181999203b1e..83de27b3a4f1b 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -94,7 +94,6 @@ #include <cassert> #include <cstddef> #include <cstring> -#include <fstream> #include <memory> #include <string> #include <tuple> @@ -3686,9 +3685,6 @@ void CompilerInvocation::GenerateLangArgs(const LangOptions &Opts, for (const auto &MP : Opts.MacroPrefixMap) GenerateArg(Args, OPT_fmacro_prefix_map_EQ, MP.first + "=" + MP.second, SA); - - if (!Opts.RandstructSeed.empty()) - GenerateArg(Args, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed, SA); } bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, @@ -4241,19 +4237,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, Diags.Report(diag::err_cc1_unbounded_vscale_min); } - if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_file_EQ)) { - std::ifstream SeedFile(A->getValue(0)); - - if (!SeedFile.is_open()) - Diags.Report(diag::err_drv_cannot_open_randomize_layout_seed_file) - << A->getValue(0); - - std::getline(SeedFile, Opts.RandstructSeed); - } - - if (const Arg *A = Args.getLastArg(OPT_frandomize_layout_seed_EQ)) - Opts.RandstructSeed = A->getValue(0); - return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 7b5bc7ca80b17..7d580dc5b6b3a 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -3129,23 +3129,6 @@ void CastOperation::CheckCStyleCast() { Self.Diag(OpRange.getBegin(), diag::warn_cast_function_type) << SrcType << DestType << OpRange; - if (isa<PointerType>(SrcType) && isa<PointerType>(DestType)) { - QualType SrcTy = cast<PointerType>(SrcType)->getPointeeType(); - QualType DestTy = cast<PointerType>(DestType)->getPointeeType(); - - const RecordDecl *SrcRD = SrcTy->getAsRecordDecl(); - const RecordDecl *DestRD = DestTy->getAsRecordDecl(); - - if (SrcRD && DestRD && SrcRD->hasAttr<RandomizeLayoutAttr>() && - SrcRD != DestRD) { - // The struct we are casting the pointer from was randomized. - Self.Diag(OpRange.getBegin(), diag::err_cast_from_randomized_struct) - << SrcType << DestType; - SrcExpr = ExprError(); - return; - } - } - DiagnoseCastOfObjCSEL(Self, SrcExpr, DestType); DiagnoseCallingConvCast(Self, SrcExpr, DestType, OpRange); DiagnoseBadFunctionCast(Self, SrcExpr, DestType); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a99b9833b3f53..51b630500f74f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -24,7 +24,6 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/NonTrivialTypeVisitor.h" -#include "clang/AST/Randstruct.h" #include "clang/AST/StmtCXX.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/PartialDiagnostic.h" @@ -17969,18 +17968,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, // Handle attributes before checking the layout. ProcessDeclAttributeList(S, Record, Attrs); - // Maybe randomize the field order. - if (!getLangOpts().CPlusPlus && Record->hasAttr<RandomizeLayoutAttr>() && - !Record->isUnion() && !getLangOpts().RandstructSeed.empty() && - !Record->isRandomized()) { - SmallVector<Decl *, 32> OrigFieldOrdering(Record->fields()); - SmallVector<Decl *, 32> NewFieldOrdering; - if (randstruct::randomizeStructureLayout( - Context, Record->getNameAsString(), OrigFieldOrdering, - NewFieldOrdering)) - Record->reorderFields(NewFieldOrdering); - } - // We may have deferred checking for a deleted destructor. Check now. if (CXXRecord) { auto *Dtor = CXXRecord->getDestructor(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 843ddbd7e3229..4b5201db7517c 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5121,21 +5121,6 @@ static void handleLifetimeCategoryAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } -static void handleRandomizeLayoutAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (checkAttrMutualExclusion<NoRandomizeLayoutAttr>(S, D, AL)) - return; - if (!D->hasAttr<RandomizeLayoutAttr>()) - D->addAttr(::new (S.Context) RandomizeLayoutAttr(S.Context, AL)); -} - -static void handleNoRandomizeLayoutAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - if (checkAttrMutualExclusion<RandomizeLayoutAttr>(S, D, AL)) - return; - if (!D->hasAttr<NoRandomizeLayoutAttr>()) - D->addAttr(::new (S.Context) NoRandomizeLayoutAttr(S.Context, AL)); -} - bool Sema::CheckCallingConvAttr(const ParsedAttr &Attrs, CallingConv &CC, const FunctionDecl *FD) { if (Attrs.isInvalid()) @@ -8650,12 +8635,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_Section: handleSectionAttr(S, D, AL); break; - case ParsedAttr::AT_RandomizeLayout: - handleRandomizeLayoutAttr(S, D, AL); - break; - case ParsedAttr::AT_NoRandomizeLayout: - handleNoRandomizeLayoutAttr(S, D, AL); - break; case ParsedAttr::AT_CodeSeg: handleCodeSegAttr(S, D, AL); break; diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 0713252385885..daae71f5167c4 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -104,7 +104,6 @@ // CHECK-NEXT: NoMicroMips (SubjectMatchRule_function) // CHECK-NEXT: NoMips16 (SubjectMatchRule_function) // CHECK-NEXT: NoProfileFunction (SubjectMatchRule_function) -// CHECK-NEXT: NoRandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: NoSanitize (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSanitizeSpecific (SubjectMatchRule_function, SubjectMatchRule_variable_is_global) // CHECK-NEXT: NoSpeculativeLoadHardening (SubjectMatchRule_function, SubjectMatchRule_objc_method) @@ -149,7 +148,6 @@ // CHECK-NEXT: PassObjectSize (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: PatchableFunctionEntry (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: Pointer (SubjectMatchRule_record_not_is_union) -// CHECK-NEXT: RandomizeLayout (SubjectMatchRule_record) // CHECK-NEXT: ReleaseHandle (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: RenderScriptKernel (SubjectMatchRule_function) // CHECK-NEXT: ReqdWorkGroupSize (SubjectMatchRule_function) diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt index 2dcef2d2fca0e..ab718d192024e 100644 --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -25,7 +25,6 @@ add_clang_unittest(ASTTests EvaluateAsRValueTest.cpp ExternalASTSourceTest.cpp NamedDeclPrinterTest.cpp - RandstructTest.cpp RecursiveASTVisitorTest.cpp SizelessTypesTest.cpp SourceLocationTest.cpp diff --git a/clang/unittests/AST/RandstructTest.cpp b/clang/unittests/AST/RandstructTest.cpp deleted file mode 100644 index 932ef7b3c48cc..0000000000000 --- a/clang/unittests/AST/RandstructTest.cpp +++ /dev/null @@ -1,442 +0,0 @@ -//===- unittest/AST/RandstructTest.cpp ------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file contains tests for Clang's structure field layout randomization. -// -//===----------------------------------------------------------------------===// - -/* - * Build this test suite by running `make ASTTests` in the build folder. - * - * Run this test suite by running the following in the build folder: - * ` ./tools/clang/unittests/AST/ASTTests - * --gtest_filter=StructureLayoutRandomization*` - */ - -#include "clang/AST/Randstruct.h" -#include "gtest/gtest.h" - -#include "DeclMatcher.h" -#include "clang/AST/RecordLayout.h" -#include "clang/ASTMatchers/ASTMatchers.h" -#include "clang/Frontend/ASTUnit.h" -#include "clang/Testing/CommandLineArgs.h" -#include "clang/Tooling/Tooling.h" - -#include <vector> - -using namespace clang; -using namespace clang::ast_matchers; -using namespace clang::randstruct; - -using field_names = std::vector<std::string>; - -namespace { - -std::unique_ptr<ASTUnit> makeAST(const std::string &SourceCode) { - std::vector<std::string> Args = getCommandLineArgsForTesting(Lang_C99); - Args.push_back("-frandomize-layout-seed=1234567890abcdef"); - - IgnoringDiagConsumer IgnoringConsumer = IgnoringDiagConsumer(); - - return tooling::buildASTFromCodeWithArgs( - SourceCode, Args, "input.c", "clang-tool", - std::make_shared<PCHContainerOperations>(), - tooling::getClangStripDependencyFileAdjuster(), - tooling::FileContentMappings(), &IgnoringConsumer); -} - -RecordDecl *getRecordDeclFromAST(const ASTContext &C, const std::string &Name) { - RecordDecl *RD = FirstDeclMatcher<RecordDecl>().match( - C.getTranslationUnitDecl(), recordDecl(hasName(Name))); - return RD; -} - -std::vector<std::string> getFieldNamesFromRecord(const RecordDecl *RD) { - std::vector<std::string> Fields; - - Fields.reserve(8); - for (auto *Field : RD->fields()) - Fields.push_back(Field->getNameAsString()); - - return Fields; -} - -bool isSubsequence(const field_names &Seq, const field_names &Subseq) { - unsigned SeqLen = Seq.size(); - unsigned SubLen = Subseq.size(); - - bool IsSubseq = false; - for (unsigned I = 0; I < SeqLen; ++I) - if (Seq[I] == Subseq[0]) { - IsSubseq = true; - for (unsigned J = 0; J + I < SeqLen && J < SubLen; ++J) { - if (Seq[J + I] != Subseq[J]) { - IsSubseq = false; - break; - } - } - } - - return IsSubseq; -} - -} // end anonymous namespace - -namespace clang { -namespace ast_matchers { - -#define RANDSTRUCT_TEST_SUITE_TEST StructureLayoutRandomizationTestSuiteTest - -TEST(RANDSTRUCT_TEST_SUITE_TEST, CanDetermineIfSubsequenceExists) { - const field_names Seq = {"a", "b", "c", "d"}; - - EXPECT_TRUE(isSubsequence(Seq, {"b", "c"})); - EXPECT_TRUE(isSubsequence(Seq, {"a", "b", "c", "d"})); - EXPECT_TRUE(isSubsequence(Seq, {"b", "c", "d"})); - EXPECT_TRUE(isSubsequence(Seq, {"a"})); - EXPECT_FALSE(isSubsequence(Seq, {"a", "d"})); -} - -#define RANDSTRUCT_TEST StructureLayoutRandomization - -TEST(RANDSTRUCT_TEST, UnmarkedStruct) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - }; - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); - const field_names Expected = {"bacon", "lettuce", "tomato", "mayonnaise"}; - - EXPECT_FALSE(RD->hasAttr<RandomizeLayoutAttr>()); - EXPECT_FALSE(RD->isRandomized()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, MarkedNoRandomize) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - } __attribute__((no_randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); - const field_names Expected = {"bacon", "lettuce", "tomato", "mayonnaise"}; - - EXPECT_TRUE(RD->hasAttr<NoRandomizeLayoutAttr>()); - EXPECT_FALSE(RD->isRandomized()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, MarkedRandomize) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); - const field_names Expected = {"lettuce", "bacon", "mayonnaise", "tomato"}; - - EXPECT_TRUE(RD->hasAttr<RandomizeLayoutAttr>()); - EXPECT_TRUE(RD->isRandomized()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, MismatchedAttrsDeclVsDef) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test __attribute__((randomize_layout)); - struct test { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - } __attribute__((no_randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - DiagnosticsEngine &Diags = AST->getDiagnostics(); - - EXPECT_FALSE(Diags.hasFatalErrorOccurred()); - EXPECT_FALSE(Diags.hasUncompilableErrorOccurred()); - EXPECT_FALSE(Diags.hasUnrecoverableErrorOccurred()); - EXPECT_EQ(Diags.getNumWarnings(), 1u); - EXPECT_EQ(Diags.getNumErrors(), 0u); -} - -TEST(RANDSTRUCT_TEST, MismatchedAttrsRandomizeVsNoRandomize) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test2 { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - } __attribute__((randomize_layout)) __attribute__((no_randomize_layout)); - )c"); - - EXPECT_TRUE(AST->getDiagnostics().hasErrorOccurred()); - - DiagnosticsEngine &Diags = AST->getDiagnostics(); - - EXPECT_TRUE(Diags.hasUncompilableErrorOccurred()); - EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred()); - EXPECT_EQ(Diags.getNumWarnings(), 0u); - EXPECT_EQ(Diags.getNumErrors(), 1u); -} - -TEST(RANDSTRUCT_TEST, MismatchedAttrsNoRandomizeVsRandomize) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test3 { - int bacon; - long lettuce; - long long tomato; - float mayonnaise; - } __attribute__((no_randomize_layout)) __attribute__((randomize_layout)); - )c"); - - EXPECT_TRUE(AST->getDiagnostics().hasErrorOccurred()); - - DiagnosticsEngine &Diags = AST->getDiagnostics(); - - EXPECT_TRUE(Diags.hasUncompilableErrorOccurred()); - EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred()); - EXPECT_EQ(Diags.getNumWarnings(), 0u); - EXPECT_EQ(Diags.getNumErrors(), 1u); -} - -TEST(RANDSTRUCT_TEST, CheckAdjacentBitfieldsRemainAdjacentAfterRandomization) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test { - int a; - int b; - int x : 1; - int y : 1; - int z : 1; - int c; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); - - const field_names Expected = {"a", "b", "c", "x", "y", "z"}; - const field_names Subseq = {"x", "y", "z"}; - const field_names Actual = getFieldNamesFromRecord(RD); - - EXPECT_TRUE(isSubsequence(Actual, Subseq)); - EXPECT_EQ(Expected, Actual); -} - -TEST(RANDSTRUCT_TEST, CheckVariableLengthArrayMemberRemainsAtEndOfStructure) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test { - int a; - double b; - short c; - char name[]; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); - const field_names Expected = {"c", "a", "name", "b"}; - - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, RandstructDoesNotOverrideThePackedAttr) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test_struct { - char a; - float b[3]; - short c; - int d; - } __attribute__((packed, randomize_layout)); - - struct another_struct { - char a; - char b[5]; - int c; - } __attribute__((packed, randomize_layout)); - - struct last_struct { - char a; - long long b; - int c[]; - } __attribute__((packed, randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - // FIXME (?): calling getASTRecordLayout is probably a necessary evil so that - // Clang's RecordBuilders can actually flesh out the information like - // alignment, etc. - { - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "test_struct"); - const ASTRecordLayout *Layout = - &AST->getASTContext().getASTRecordLayout(RD); - const field_names Expected = {"b", "a", "c", "d"}; - - EXPECT_EQ(19, Layout->getSize().getQuantity()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - } - - { - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "another_struct"); - const ASTRecordLayout *Layout = - &AST->getASTContext().getASTRecordLayout(RD); - const field_names Expected = {"c", "b", "a"}; - - EXPECT_EQ(10, Layout->getSize().getQuantity()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - } - - { - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "last_struct"); - const ASTRecordLayout *Layout = - &AST->getASTContext().getASTRecordLayout(RD); - const field_names Expected = {"a", "c", "b"}; - - EXPECT_EQ(9, Layout->getSize().getQuantity()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - } -} - -TEST(RANDSTRUCT_TEST, ZeroWidthBitfieldsSeparateAllocationUnits) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test_struct { - int a : 1; - int : 0; - int b : 1; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "test_struct"); - const field_names Expected = {"b", "a", ""}; - - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, RandstructDoesNotRandomizeUnionFieldOrder) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - union test_union { - int a; - int b; - int c; - int d; - int e; - int f; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "test_union"); - const field_names Expected = {"a", "b", "c", "d", "e", "f"}; - - EXPECT_FALSE(RD->isRandomized()); - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); -} - -TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsRetainFieldOrder) { - const std::unique_ptr<ASTUnit> AST = makeAST(R"c( - struct test_struct { - int a; - struct sub_struct { - int b; - int c; - int d; - int e; - int f; - } __attribute__((randomize_layout)) s; - int f; - struct { - int g; - int h; - int i; - int j; - int k; - }; - int l; - union { - int m; - int n; - int o; - int p; - int q; - }; - int r; - } __attribute__((randomize_layout)); - )c"); - - EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "test_struct"); - const field_names Expected = {"", "l", "r", "f", "a", "s", ""}; - - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - - bool AnonStructTested = false; - bool AnonUnionTested = false; - for (const Decl *D : RD->decls()) - if (const FieldDecl *FD = dyn_cast<FieldDecl>(D)) { - if (const auto *Record = FD->getType()->getAs<RecordType>()) { - RD = Record->getDecl(); - if (RD->isAnonymousStructOrUnion()) { - if (RD->isUnion()) { - const field_names Expected = {"m", "n", "o", "p", "q"}; - - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - AnonUnionTested = true; - } else { - const field_names Expected = {"g", "h", "i", "j", "k"}; - - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - AnonStructTested = true; - } - } else if (RD->isStruct()) { - const field_names Expected = {"c", "b", "e", "d", "f"}; - EXPECT_EQ(Expected, getFieldNamesFromRecord(RD)); - } - } - } - - EXPECT_TRUE(AnonStructTested); - EXPECT_TRUE(AnonUnionTested); -} - -} // namespace ast_matchers -} // namespace clang diff --git a/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn index 3fb5981ef9328..aee4db327096f 100644 --- a/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/lib/AST/BUILD.gn @@ -126,7 +126,6 @@ static_library("AST") { "ParentMapContext.cpp", "PrintfFormatString.cpp", "QualTypeNames.cpp", - "Randstruct.cpp", "RawCommentList.cpp", "RecordLayout.cpp", "RecordLayoutBuilder.cpp", diff --git a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn index 803b9eb7eb105..c275553d01c96 100644 --- a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn @@ -34,7 +34,6 @@ unittest("ASTTests") { "EvaluateAsRValueTest.cpp", "ExternalASTSourceTest.cpp", "NamedDeclPrinterTest.cpp", - "RandstructTest.cpp", "RecursiveASTVisitorTest.cpp", "SizelessTypesTest.cpp", "SourceLocationTest.cpp", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits