diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -18046,7 +18046,7 @@ if (!getLangOpts().CPlusPlus && Record->hasAttr() && !Record->isUnion() && !getLangOpts().RandstructSeed.empty() && !Record->isRandomized()) { - SmallVector OrigFieldOrdering(Record->fields()); + SmallVector OrigFieldOrdering(Record->decls()); SmallVector NewFieldOrdering; if (randstruct::randomizeStructureLayout( Context, Record->getNameAsString(), OrigFieldOrdering, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -2123,7 +2123,7 @@ // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->castAs()->getDecl(); RecordDecl::field_iterator FieldEnd = RD->field_end(); - size_t NumRecordFields = std::distance(RD->field_begin(), RD->field_end()); + size_t NumRecordFields = std::distance(RD->decls_begin(), RD->decls_end()); bool CheckForMissingFields = !IList->isIdiomaticZeroInitializer(SemaRef.getLangOpts()); bool HasDesignatedInit = false; diff --git a/clang/unittests/AST/RandstructTest.cpp b/clang/unittests/AST/RandstructTest.cpp --- a/clang/unittests/AST/RandstructTest.cpp +++ b/clang/unittests/AST/RandstructTest.cpp @@ -159,9 +159,12 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_FALSE(RD->hasAttr()); EXPECT_FALSE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, MarkedNoRandomize) { @@ -177,9 +180,12 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->hasAttr()); EXPECT_FALSE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, MarkedRandomize) { @@ -195,9 +201,12 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->hasAttr()); EXPECT_TRUE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, MismatchedAttrsDeclVsDef) { @@ -280,11 +289,14 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); const field_names Actual = getFieldNamesFromRecord(RD); const field_names Subseq = {"x", "y", "z"}; EXPECT_TRUE(RD->isRandomized()); EXPECT_TRUE(isSubsequence(Actual, Subseq)); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, CheckVariableLengthArrayMemberRemainsAtEndOfStructure) { @@ -300,8 +312,11 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, RandstructDoesNotOverrideThePackedAttr) { @@ -340,9 +355,12 @@ getRecordDeclFromAST(AST->getASTContext(), "test_struct"); const ASTRecordLayout *Layout = &AST->getASTContext().getASTRecordLayout(RD); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); EXPECT_EQ(19, Layout->getSize().getQuantity()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } { @@ -350,9 +368,12 @@ getRecordDeclFromAST(AST->getASTContext(), "another_struct"); const ASTRecordLayout *Layout = &AST->getASTContext().getASTRecordLayout(RD); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); EXPECT_EQ(10, Layout->getSize().getQuantity()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } { @@ -360,9 +381,12 @@ getRecordDeclFromAST(AST->getASTContext(), "last_struct"); const ASTRecordLayout *Layout = &AST->getASTContext().getASTRecordLayout(RD); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); EXPECT_EQ(9, Layout->getSize().getQuantity()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } } @@ -378,8 +402,11 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, RandstructDoesNotRandomizeUnionFieldOrder) { @@ -396,10 +423,12 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); - const RecordDecl *RD = - getRecordDeclFromAST(AST->getASTContext(), "test"); + const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_FALSE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); } TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsRetainFieldOrder) { @@ -436,8 +465,11 @@ EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); EXPECT_TRUE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); bool AnonStructTested = false; bool AnonUnionTested = false; @@ -467,5 +499,35 @@ EXPECT_TRUE(AnonUnionTested); } +TEST(RANDSTRUCT_TEST, AnonymousStructsAndUnionsReferenced) { + std::unique_ptr AST = makeAST(R"c( + struct test { + int bacon; + long lettuce; + struct { double avocado; char blech; }; + long long tomato; + union { char toast[8]; unsigned toast_thing; }; + float mayonnaise; + } __attribute__((randomize_layout)); + + int foo(struct test *t) { + return t->blech; + } + + char *bar(struct test *t) { + return t->toast; + } + )c"); + + EXPECT_FALSE(AST->getDiagnostics().hasErrorOccurred()); + + const RecordDecl *RD = getRecordDeclFromAST(AST->getASTContext(), "test"); + long OriginalDeclCount = std::distance(RD->decls_begin(), RD->decls_end()); + + EXPECT_TRUE(RD->isRandomized()); + EXPECT_EQ(OriginalDeclCount, + std::distance(RD->decls_begin(), RD->decls_end())); +} + } // namespace ast_matchers } // namespace clang