diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11588,7 +11588,10 @@ 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. +// Layout randomization diagnostics. +def err_non_designated_init_used : Error< + "non-designated initializers cannot be used on a randomized struct">; def err_cast_from_randomized_struct : Error< "casting from randomized structure pointer type %0 to %1">; + } // end of sema component. 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 @@ -2176,6 +2176,14 @@ break; } + // Don't allow non-designated initializers on randomized structures. + if (RD->isRandomized()) { + if (!VerifyOnly) + SemaRef.Diag(InitLoc, diag::err_non_designated_init_used); + hadError = true; + break; + } + // We've already initialized a member of a union. We're done. if (InitializedSomething && DeclType->isUnionType()) break; 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 @@ -156,68 +156,6 @@ EXPECT_TRUE(RD->isRandomized()); } -TEST(RANDSTRUCT_TEST, MismatchedAttrsDeclVsDef) { - const std::unique_ptr 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 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 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 AST = makeAST(R"c( struct test { @@ -417,5 +355,133 @@ EXPECT_TRUE(AnonUnionTested); } +TEST(RANDSTRUCT_TEST, MismatchedAttrsDeclVsDef) { + const std::unique_ptr 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 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 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, RandomizedStructWithDesignatedInit) { + const std::unique_ptr AST = makeAST(R"c( + typedef void (*func_ptr)(); + + void foo(void); + void bar(void); + void baz(void); + void gaz(void); + + struct test { + func_ptr a; + func_ptr b; + func_ptr c; + func_ptr d; + func_ptr e; + func_ptr f; + func_ptr g; + } __attribute__((randomize_layout)) inst = { + .f = baz, .b = bar, .g = gaz, .a = foo + }; + )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(), 0u); + EXPECT_EQ(Diags.getNumErrors(), 0u); +} + +TEST(RANDSTRUCT_TEST, RandomizedStructWithNonDesignatedInit) { + const std::unique_ptr AST = makeAST(R"c( + typedef void (*func_ptr)(); + + void foo(void); + void bar(void); + void baz(void); + void gaz(void); + + struct test { + func_ptr a; + func_ptr b; + func_ptr c; + func_ptr d; + func_ptr e; + func_ptr f; + func_ptr g; + } __attribute__((randomize_layout)) inst = { + baz, bar, gaz, foo + }; + )c"); + + EXPECT_TRUE(AST->getDiagnostics().hasErrorOccurred()); + + DiagnosticsEngine &Diags = AST->getDiagnostics(); + + EXPECT_FALSE(Diags.hasFatalErrorOccurred()); + EXPECT_TRUE(Diags.hasUncompilableErrorOccurred()); + EXPECT_TRUE(Diags.hasUnrecoverableErrorOccurred()); + EXPECT_EQ(Diags.getNumWarnings(), 0u); + EXPECT_EQ(Diags.getNumErrors(), 1u); +} + } // namespace ast_matchers } // namespace clang