diff --git a/build/clang-plugin/CustomTypeAnnotation.cpp b/build/clang-plugin/CustomTypeAnnotation.cpp index b61538ecc346..8a6d85e3b914 100644 --- a/build/clang-plugin/CustomTypeAnnotation.cpp +++ b/build/clang-plugin/CustomTypeAnnotation.cpp @@ -15,8 +15,6 @@ CustomTypeAnnotation HeapClass = CustomTypeAnnotation("moz_heap_class", "heap"); CustomTypeAnnotation NonTemporaryClass = CustomTypeAnnotation("moz_non_temporary_class", "non-temporary"); -CustomTypeAnnotation NonParam = - CustomTypeAnnotation("moz_non_param", "non-param"); void CustomTypeAnnotation::dumpAnnotationReason(BaseCheck &Check, QualType T, diff --git a/build/clang-plugin/CustomTypeAnnotation.h b/build/clang-plugin/CustomTypeAnnotation.h index aa80def6ea3c..1069a30fe3bc 100644 --- a/build/clang-plugin/CustomTypeAnnotation.h +++ b/build/clang-plugin/CustomTypeAnnotation.h @@ -67,6 +67,5 @@ extern CustomTypeAnnotation GlobalClass; extern CustomTypeAnnotation NonHeapClass; extern CustomTypeAnnotation HeapClass; extern CustomTypeAnnotation NonTemporaryClass; -extern CustomTypeAnnotation NonParam; #endif diff --git a/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp b/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp index 198bb8a503bd..ef6920f7ff38 100644 --- a/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp +++ b/build/clang-plugin/NonParamInsideFunctionDeclChecker.cpp @@ -5,6 +5,45 @@ #include "NonParamInsideFunctionDeclChecker.h" #include "CustomMatchers.h" +class NonParamAnnotation : public CustomTypeAnnotation +{ +public: + NonParamAnnotation() : CustomTypeAnnotation("moz_non_param", "non-param") {}; + +protected: + // Adding alignas(_) on a struct implicitly marks it as MOZ_NON_PARAM, due to + // MSVC limitations which prevent passing explcitly aligned types by value as + // parameters. This overload of hasFakeAnnotation injects fake MOZ_NON_PARAM + // annotations onto these types. + bool hasFakeAnnotation(const TagDecl *D) const override { + // Check if the decl itself has an AlignedAttr on it. + for (const Attr *A : D->attrs()) { + if (isa(A)) { + D->dump(); + return true; + } + } + + // Check if any of the decl's fields have an AlignedAttr on them. + if (auto RD = dyn_cast(D)) { + for (auto F : RD->fields()) { + for (auto A : F->attrs()) { + if (isa(A)) { + D->dump(); + + return true; + } + } + } + } + + // We don't need to check the types of fields, as the CustomTypeAnnotation + // infrastructure will handle that for us. + return false; + } +}; +NonParamAnnotation NonParam; + void NonParamInsideFunctionDeclChecker::registerMatchers(MatchFinder* AstMatcher) { AstMatcher->addMatcher( functionDecl(anyOf(allOf(isDefinition(), diff --git a/build/clang-plugin/tests/TestNonParameterChecker.cpp b/build/clang-plugin/tests/TestNonParameterChecker.cpp index 87ff89238731..340cfd814231 100644 --- a/build/clang-plugin/tests/TestNonParameterChecker.cpp +++ b/build/clang-plugin/tests/TestNonParameterChecker.cpp @@ -177,3 +177,13 @@ void testLambda() (void)[](HasNonParamUnion x) -> void {}; //expected-error {{Type 'HasNonParamUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} (void)[](HasNonParamStructUnion x) -> void {}; //expected-error {{Type 'HasNonParamStructUnion' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} } + +// Check that alignas() implies the MOZ_NON_PARAM attribute. + +struct alignas(8) AlignasStruct { char a; }; +void takesAlignasStruct(AlignasStruct x) { } // expected-error {{Type 'AlignasStruct' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +void takesAlignasStructByRef(const AlignasStruct& x) { } + +struct AlignasMember { alignas(8) char a; }; +void takesAlignasMember(AlignasMember x) { } // expected-error {{Type 'AlignasMember' must not be used as parameter}} expected-note {{Please consider passing a const reference instead}} +void takesAlignasMemberByRef(const AlignasMember& x) { }