----- Original Message ----- > From: "Aaron Ballman" <aaron.ball...@gmail.com> > To: "Hal Finkel" <hfin...@anl.gov> > Cc: reviews+d10599+public+2871690e17faf...@reviews.llvm.org, "Richard Smith" > <rich...@metafoo.co.uk>, "Eric Stotzer" > <ejstot...@gmail.com>, "Michael Wong" <fraggamuf...@gmail.com>, "llvm cfe" > <cfe-commits@cs.uiuc.edu>, "Alexey > Bataev" <a.bat...@hotmail.com> > Sent: Tuesday, July 7, 2015 7:44:13 AM > Subject: Re: [PATCH] [OPENMP] Initial support for '#pragma omp declare simd' > directive. > > On Tue, Jul 7, 2015 at 8:35 AM, Hal Finkel <hfin...@anl.gov> wrote: > > ----- Original Message ----- > >> From: "Aaron Ballman" <aaron.ball...@gmail.com> > >> To: "Alexey Bataev" <a.bat...@hotmail.com> > >> Cc: reviews+d10599+public+2871690e17faf...@reviews.llvm.org, > >> "Richard Smith" <rich...@metafoo.co.uk>, "Hal Finkel" > >> <hfin...@anl.gov>, ejstot...@gmail.com, fraggamuf...@gmail.com, > >> "llvm cfe" <cfe-commits@cs.uiuc.edu> > >> Sent: Tuesday, July 7, 2015 7:18:04 AM > >> Subject: Re: [PATCH] [OPENMP] Initial support for '#pragma omp > >> declare simd' directive. > >> > >> On Tue, Jul 7, 2015 at 7:40 AM, Bataev, Alexey > >> <a.bat...@hotmail.com> > >> wrote: > >> >> I tend to agree with hal that this should be a warning. It's > >> >> low > >> >> priority, definitely, but silently allowing the programmer to > >> >> get > >> >> away > >> >> with incorrect code doesn't seem beneficial to anyone. It would > >> >> also > >> >> point out the two other places in your tests that have this > >> >> exact > >> >> same > >> >> code pattern with no additional testing benefit. ;-) > >> > > >> > > >> > This code is correct, OpenMP standard allows to mark the same > >> > function many > >> > times with the same pragma. Here is an excerpt: > >> > >> Eww, but fair enough. :-) > > > > Okay, but this was not my point. I did not say it should be an > > error. Warnings are not for incorrect code, they are for correct > > code were we feel the user *probably* intended something else. If > > a function is marked with several identical 'omp declare simd' > > pragmas, is that likely to be intentional or a mistake of some > > kind? > > > > Even if we decide on a warning here, I'm fine with adding it in > > follow-up. I think it would need to account for the other clauses > > as well anyway. > > My acquiescence is because the standard says it's a well-formed > construct, and I'm somewhat hesitant to diagnose on well-formed, > benign code. But I also agree with your logic on whether this is code > the user intended or not. I suspect with macros, intention becomes > slightly more muddy. > > Btw, is this expected to work?
Yes, I believe that should work. -Hal > > // a.h > #pragma omp declare simd > > // a.cpp > #include "a.h" > void f() {} > > ~Aaron > > > > > Thanks again, > > Hal > > > >> > >> > > >> > #pragma omp declare simd [clause[[,] clause] ...] new-line > >> > [#pragma omp declare simd [clause[[,] clause] ...] new-line] > >> > [...] > >> > function definition or declaration > >> > > >> > There may be multiple declare simd directives for a function (C, > >> > C++, > >> > Fortran) or subroutine (Fortran). > >> > > >> >> > >> >> I would also like to see a test for #pragma omp declare simd > >> >> that > >> >> is > >> >> at the end of the TU with no futher statements (to ensure it > >> >> gets > >> >> diagnosed). > >> > > >> > > >> > Ok, will be added. > >> > > >> >> Copy paste error? > >> > > >> > Nope, I have to verify that the compiler allows to mark the same > >> > function > >> > several times with '#pragma omp declare simd' according to > >> > standard. > >> > >> Fair, but we don't need that tested multiple times. > >> > >> > > >> >> This attribute has a pragma spelling where the namespace is > >> >> openmp > >> >> and > >> >> the name is declare. It's the same pattern used by the loop > >> >> hint > >> >> and > >> >> init_seg pragmas. > >> > > >> > > >> > Can't add spellings, it breaks -ast-print mode (pragmas are > >> > printed > >> > just > >> > like attributes, directly after function declaration). > >> > >> That means -ast-print is broken and should be fixed. > >> > >> > > >> >> Please document this attribute as it does have a pragma > >> >> spelling. > >> > > >> > > >> > Will add > >> > > >> >> This attribute appears to be missing its Subjects clause as > >> >> well. > >> >> That's not information we currently care about for pragmas, but > >> >> I > >> >> would like the declarative part of the attribute to match the > >> >> semantic > >> >> expectations. > >> > > >> > > >> > Will add too. > >> > > >> >> I've not seen any tests for ObjC, so does this really apply to > >> >> methods? > >> > > >> > I'll fix this message. > >> > > >> >> Capitalize the first word in the documentation part of the > >> >> sentence. > >> > > >> > Thanks, fixed. > >> > > >> >> > >> >> Drop the virtual, add override. > >> > > >> > Fixed. > >> > > >> >> Drop the "if" > >> > > >> > Fixed > >> > > >> >> Can you use a range-based for loop please? > >> > > >> > Done > >> > > >> >> This is not an implicit attribute because it's the direct > >> >> result > >> >> of > >> >> the user typing something in source code. > >> > > >> > Fixed. > >> > > >> >> This really weirds me out. That means this function doesn't > >> >> parse > >> >> just > >> >> the pragma, it also parses any external declaration. > >> > > >> > Yes, we have to parse function right after pragma to be able > >> > correctly > >> > handle clauses associated with this pragma. These clauses may > >> > have > >> > refernces > >> > to function arguments and because of that we have to parse the > >> > function > >> > first and only then the pragma itself. > >> > >> Can we update the name of the function to suggest this? > >> > >> > > >> >> The comments don't look correct here. > >> > > >> > Missed this one, thanks. > >> > > >> >> Is this safe to assert in a parsing method, or should this be > >> >> diagnosed? > >> > > >> > There always must be at least one token if the compiler works > >> > correctly - > >> > tok::annot_pragma_openmp. No need to diagnose. > >> > >> Good deal, thank you! > >> > >> > > >> >> Has this situation already been diagnosed? If so, then why are > >> >> we > >> >> generating the tokens in a way that require this work? And if > >> >> not, > >> >> are > >> >> we missing a diagnostic here? > >> > > >> > Yes, this was diagnosed already. We need to remove cached > >> > tokens, > >> > so just > >> > skip them. > >> > >> Thank you! > >> > >> ~Aaron > >> > >> > > >> >> Attribute is not implicit. > >> > > >> > Fixed. > >> > > >> > Best regards, > >> > Alexey Bataev > >> > ============= > >> > Software Engineer > >> > Intel Compiler Team > >> > > >> > 06.07.2015 16:13, Aaron Ballman пишет: > >> > > >> >> On Mon, Jun 22, 2015 at 7:35 AM, Alexey Bataev > >> >> <a.bat...@hotmail.com> > >> >> wrote: > >> >>> > >> >>> Hi rsmith, aaron.ballman, hfinkel, ejstotzer, fraggamuffin, > >> >>> > >> >>> Inital parsing/sema/serialization/deserialization support for > >> >>> '#pragma > >> >>> omp declare simd' directive. > >> >>> The declare simd construct can be applied to a function to > >> >>> enable > >> >>> the > >> >>> creation of one or more versions that can process multiple > >> >>> arguments using > >> >>> SIMD instructions from a single invocation from a SIMD loop. > >> >>> If the function has any declarations, then the declare simd > >> >>> construct for > >> >>> any declaration that has one must be equivalent to the one > >> >>> specified for the > >> >>> definition. Otherwise, the result is unspecified. > >> >>> This pragma can be aplied many times to the same declaration. > >> >>> Internally this pragma is represented as an attribute. But we > >> >>> need > >> >>> special processing for this pragma because it must be used > >> >>> before > >> >>> function > >> >>> declaration, this directive is appplied to. > >> >>> If pragma is applied to method declared/defined in the class > >> >>> lexical > >> >>> context, then the delayed parsing procedure is used. > >> >>> Also delayed parsing is used for poarsing a pragma itself, > >> >>> because this > >> >>> directive has several clauses that can reference arguments of > >> >>> the > >> >>> associated > >> >>> function/method. > >> >>> > >> >>> http://reviews.llvm.org/D10599 > >> >>> > >> >>> Files: > >> >>> include/clang/AST/ASTMutationListener.h > >> >>> include/clang/Basic/Attr.td > >> >>> include/clang/Basic/DiagnosticParseKinds.td > >> >>> include/clang/Basic/DiagnosticSemaKinds.td > >> >>> include/clang/Basic/OpenMPKinds.def > >> >>> include/clang/Parse/Parser.h > >> >>> include/clang/Sema/Sema.h > >> >>> include/clang/Serialization/ASTWriter.h > >> >>> lib/AST/DeclPrinter.cpp > >> >>> lib/Basic/OpenMPKinds.cpp > >> >>> lib/Frontend/MultiplexConsumer.cpp > >> >>> lib/Parse/ParseDeclCXX.cpp > >> >>> lib/Parse/ParseOpenMP.cpp > >> >>> lib/Parse/Parser.cpp > >> >>> lib/Sema/SemaOpenMP.cpp > >> >>> lib/Serialization/ASTCommon.h > >> >>> lib/Serialization/ASTReaderDecl.cpp > >> >>> lib/Serialization/ASTWriter.cpp > >> >>> test/OpenMP/declare_simd_ast_print.c > >> >>> test/OpenMP/declare_simd_ast_print.cpp > >> >>> test/OpenMP/declare_simd_messages.cpp > >> >>> > >> >>> EMAIL PREFERENCES > >> >>> http://reviews.llvm.org/settings/panel/emailpreferences/ > >> >> > >> >> Index: test/OpenMP/declare_simd_messages.cpp > >> >> =================================================================== > >> >> --- test/OpenMP/declare_simd_messages.cpp > >> >> +++ test/OpenMP/declare_simd_messages.cpp > >> >> @@ -0,0 +1,45 @@ > >> >> +// RUN: %clang_cc1 -triple x86_64-apple-macos10.7.0 -verify > >> >> -fopenmp > >> >> -x c++ -std=c++11 %s > >> >> + > >> >> +// expected-error@+1 {{expected an OpenMP directive}} > >> >> +#pragma omp declare > >> >> + > >> >> +// expected-error@+2 {{'#pragma omp declare simd' can be > >> >> applied > >> >> to > >> >> functions or methods only}} > >> >> +#pragma omp declare simd > >> >> +int a; > >> >> +// expected-error@+2 {{'#pragma omp declare simd' can be > >> >> applied > >> >> to > >> >> functions or methods only}} > >> >> +#pragma omp declare simd > >> >> +#pragma omp threadprivate(a) > >> >> +int var; > >> >> +#pragma omp threadprivate(var) > >> >> + > >> >> +// expected-error@+2 {{expected an OpenMP directive}} > >> >> +#pragma omp declare simd > >> >> +#pragma omp declare > >> >> + > >> >> +#pragma omp declare simd > >> >> +#pragma omp declare simd > >> >> > >> >> I tend to agree with hal that this should be a warning. It's > >> >> low > >> >> priority, definitely, but silently allowing the programmer to > >> >> get > >> >> away > >> >> with incorrect code doesn't seem beneficial to anyone. It would > >> >> also > >> >> point out the two other places in your tests that have this > >> >> exact > >> >> same > >> >> code pattern with no additional testing benefit. ;-) > >> >> > >> >> +int main(); > >> >> + > >> >> +#pragma omp declare simd > >> >> +template <class C> > >> >> +void h(C *hp, C *hp2, C *hq, C *lin) { > >> >> +} > >> >> + > >> >> +#pragma omp declare simd > >> >> +template <> > >> >> +void h(int *hp, int *hp2, int *hq, int *lin) { > >> >> + h((float *)hp, (float *)hp2, (float *)hq, (float *)lin); > >> >> +} > >> >> + > >> >> +template <class T> > >> >> +struct St { > >> >> +#pragma omp declare simd > >> >> + void h(T *hp) { > >> >> +// expected-error@+1 {{unexpected OpenMP directive '#pragma > >> >> omp > >> >> declare > >> >> simd'}} > >> >> +#pragma omp declare simd > >> >> + *hp = *t; > >> >> + } > >> >> + > >> >> +private: > >> >> + T t; > >> >> +}; > >> >> > >> >> I would also like to see a test for #pragma omp declare simd > >> >> that > >> >> is > >> >> at the end of the TU with no futher statements (to ensure it > >> >> gets > >> >> diagnosed). > >> >> > >> >> Index: test/OpenMP/declare_simd_ast_print.cpp > >> >> =================================================================== > >> >> --- test/OpenMP/declare_simd_ast_print.cpp > >> >> +++ test/OpenMP/declare_simd_ast_print.cpp > >> >> @@ -0,0 +1,103 @@ > >> >> +// RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 > >> >> -ast-print > >> >> %s | > >> >> FileCheck %s > >> >> +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t > >> >> %s > >> >> +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -include-pch %t > >> >> -fsyntax-only -verify %s -ast-print | FileCheck %s > >> >> +// expected-no-diagnostics > >> >> + > >> >> +#ifndef HEADER > >> >> +#define HEADER > >> >> + > >> >> +#pragma omp declare simd > >> >> +void add_1(float *d); > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: void add_1(float *d); > >> >> +// > >> >> + > >> >> +#pragma omp declare simd > >> >> +template <class C> void h(C *hp, C *hp2, C *hq, C *lin) { > >> >> +} > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: template <class C = int> void h(int *hp, int > >> >> *hp2, > >> >> int > >> >> *hq, int *lin) { > >> >> +// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, > >> >> (float > >> >> *)lin); > >> >> +// CHECK-NEXT: } > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: template <class C = float> void h(float *hp, > >> >> float > >> >> *hp2, float *hq, float *lin) { > >> >> +// CHECK-NEXT: } > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK: template <class C> void h(C *hp, C *hp2, C *hq, C > >> >> *lin) > >> >> { > >> >> +// CHECK-NEXT: } > >> >> +// > >> >> + > >> >> +// Instatiate with <C=int> explicitly. > >> >> +// Pragmas need to be same, otherwise standard says that's > >> >> undefined > >> >> behavior. > >> >> +#pragma omp declare simd > >> >> +template <> > >> >> +void h(int *hp, int *hp2, int *hq, int *lin) > >> >> +{ > >> >> + // Instatiate with <C=float> implicitly. > >> >> + // This is special case where the directive is stored by > >> >> Sema > >> >> and is > >> >> + // generated together with the (pending) function > >> >> instatiation. > >> >> + h((float*) hp, (float*) hp2, (float*) hq, (float*) lin); > >> >> +} > >> >> + > >> >> +class VV { > >> >> + // CHECK: #pragma omp declare simd > >> >> + // CHECK-NEXT: int add(int a, int b) { > >> >> + // CHECK-NEXT: return a + b; > >> >> + // CHECK-NEXT: } > >> >> + #pragma omp declare simd > >> >> + int add(int a, int b) { return a + b; } > >> >> + > >> >> + // CHECK: #pragma omp declare simd > >> >> + // CHECK-NEXT: #pragma omp declare simd > >> >> + // CHECK-NEXT: float addpf(float *a, float *b) { > >> >> + // CHECK-NEXT: return *a + *b; > >> >> + // CHECK-NEXT: } > >> >> + #pragma omp declare simd > >> >> + #pragma omp declare simd > >> >> > >> >> Copy paste error? > >> >> > >> >> + float addpf(float *a, float *b) { return *a + *b; } > >> >> +}; > >> >> + > >> >> +// CHECK: template <int X = 16> class TVV { > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: int tadd(int a, int b); > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: float taddpf(float *a, float *b) { > >> >> +// CHECK-NEXT: return *a + *b; > >> >> +// CHECK-NEXT: } > >> >> +// CHECK: } > >> >> +template <int X> > >> >> +class TVV { > >> >> +public: > >> >> +// CHECK: template <int X> class TVV { > >> >> + #pragma omp declare simd > >> >> + int tadd(int a, int b) { return a + b; } > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: int tadd(int a, int b) { > >> >> +// CHECK-NEXT: return a + b; > >> >> +// CHECK-NEXT: } > >> >> + > >> >> + > >> >> + #pragma omp declare simd > >> >> + float taddpf(float *a, float *b) { return *a + *b; } > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: float taddpf(float *a, float *b) { > >> >> +// CHECK-NEXT: return *a + *b; > >> >> +// CHECK-NEXT: } > >> >> +}; > >> >> +// CHECK: }; > >> >> + > >> >> +// CHECK: TVV<16> t16; > >> >> +TVV<16> t16; > >> >> + > >> >> +void f() { > >> >> + float a = 1.0f, b = 2.0f; > >> >> + float r = t16.taddpf(&a, &b); > >> >> +} > >> >> + > >> >> +#endif > >> >> Index: test/OpenMP/declare_simd_ast_print.c > >> >> =================================================================== > >> >> --- test/OpenMP/declare_simd_ast_print.c > >> >> +++ test/OpenMP/declare_simd_ast_print.c > >> >> @@ -0,0 +1,17 @@ > >> >> +// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck > >> >> %s > >> >> +// RUN: %clang_cc1 -fopenmp -emit-pch -o %t %s > >> >> +// RUN: %clang_cc1 -fopenmp -include-pch %t -fsyntax-only > >> >> -verify > >> >> %s > >> >> -ast-print | FileCheck %s > >> >> +// expected-no-diagnostics > >> >> + > >> >> +#ifndef HEADER > >> >> +#define HEADER > >> >> + > >> >> +#pragma omp declare simd > >> >> +#pragma omp declare simd > >> >> > >> >> Copy paste error? > >> >> > >> >> +void add_1(float *d, float *s1, float *s2); > >> >> + > >> >> +// CHECK: #pragma omp declare simd > >> >> +// CHECK-NEXT: #pragma omp declare simd > >> >> +// CHECK-NEXT: void add_1(float *d, float *s1, float *s2) > >> >> + > >> >> +#endif > >> >> Index: include/clang/Basic/OpenMPKinds.def > >> >> =================================================================== > >> >> --- include/clang/Basic/OpenMPKinds.def > >> >> +++ include/clang/Basic/OpenMPKinds.def > >> >> @@ -94,6 +94,7 @@ > >> >> OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd") > >> >> OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") > >> >> OPENMP_DIRECTIVE_EXT(for_simd, "for simd") > >> >> +OPENMP_DIRECTIVE_EXT(declare_simd, "declare simd") > >> >> > >> >> // OpenMP clauses. > >> >> OPENMP_CLAUSE(if, OMPIfClause) > >> >> Index: include/clang/Basic/Attr.td > >> >> =================================================================== > >> >> --- include/clang/Basic/Attr.td > >> >> +++ include/clang/Basic/Attr.td > >> >> @@ -2044,3 +2044,19 @@ > >> >> let SemaHandler = 0; > >> >> let Documentation = [Undocumented]; > >> >> } > >> >> + > >> >> +def OMPDeclareSimdDecl : InheritableAttr { > >> >> + // This attribute has no spellings as it is only ever > >> >> created > >> >> implicitly. > >> >> + let Spellings = []; > >> >> > >> >> This attribute has a pragma spelling where the namespace is > >> >> openmp > >> >> and > >> >> the name is declare. It's the same pattern used by the loop > >> >> hint > >> >> and > >> >> init_seg pragmas. > >> >> > >> >> + let SemaHandler = 0; > >> >> + let Documentation = [Undocumented]; > >> >> > >> >> Please document this attribute as it does have a pragma > >> >> spelling. > >> >> > >> >> + let Args = [UnsignedArgument<"NumberOfDirectives">, > >> >> BoolArgument<"Complete">]; > >> >> + let AdditionalMembers = [{ > >> >> + void printPrettyPragma(raw_ostream &OS, const PrintingPolicy > >> >> &Policy) > >> >> const { > >> >> + OS << "#pragma omp declare simd\n"; > >> >> + } > >> >> + void setNumberOfDirectives(unsigned N) { numberOfDirectives > >> >> = > >> >> N; } > >> >> + void setComplete() { complete = true; } > >> >> > >> >> This attribute appears to be missing its Subjects clause as > >> >> well. > >> >> That's not information we currently care about for pragmas, but > >> >> I > >> >> would like the declarative part of the attribute to match the > >> >> semantic > >> >> expectations. > >> >> > >> >> + }]; > >> >> +} > >> >> + > >> >> Index: include/clang/Basic/DiagnosticParseKinds.td > >> >> =================================================================== > >> >> --- include/clang/Basic/DiagnosticParseKinds.td > >> >> +++ include/clang/Basic/DiagnosticParseKinds.td > >> >> @@ -989,6 +989,8 @@ > >> >> "'#pragma omp %0' cannot be an immediate substatement">; > >> >> def err_omp_expected_identifier_for_critical : Error< > >> >> "expected identifier specifying the name of the 'omp > >> >> critical' > >> >> directive">; > >> >> +def err_omp_single_decl_in_declare_simd : Error< > >> >> + "single declaration is expected with 'declare simd' > >> >> directive">; > >> >> > >> >> // Pragma loop support. > >> >> def err_pragma_loop_missing_argument : Error< > >> >> Index: include/clang/Basic/DiagnosticSemaKinds.td > >> >> =================================================================== > >> >> --- include/clang/Basic/DiagnosticSemaKinds.td > >> >> +++ include/clang/Basic/DiagnosticSemaKinds.td > >> >> @@ -7601,6 +7601,8 @@ > >> >> "the 'copyprivate' clause must not be used with the > >> >> 'nowait' > >> >> clause">; > >> >> def note_omp_nowait_clause_here : Note< > >> >> "'nowait' clause is here">; > >> >> +def err_omp_function_expected : Error< > >> >> + "'#pragma omp declare simd' can be applied to functions or > >> >> methods > >> >> only">; > >> >> > >> >> I've not seen any tests for ObjC, so does this really apply to > >> >> methods? > >> >> > >> >> } // end of OpenMP category > >> >> > >> >> let CategoryName = "Related Result Type Issue" in { > >> >> Index: include/clang/Sema/Sema.h > >> >> =================================================================== > >> >> --- include/clang/Sema/Sema.h > >> >> +++ include/clang/Sema/Sema.h > >> >> @@ -144,6 +144,7 @@ > >> >> class ObjCPropertyDecl; > >> >> class ObjCProtocolDecl; > >> >> class OMPThreadPrivateDecl; > >> >> + class OMPDeclareSimdDecl; > >> >> class OMPClause; > >> >> class OverloadCandidateSet; > >> >> class OverloadExpr; > >> >> @@ -7758,6 +7759,13 @@ > >> >> Stmt *AStmt, > >> >> SourceLocation > >> >> StartLoc, > >> >> SourceLocation > >> >> EndLoc); > >> >> > >> >> + /// \brief Called on well-formed '\#pragma omp declare simd' > >> >> after > >> >> parsing of > >> >> + /// the associated method/function. > >> >> + DeclGroupPtrTy > >> >> ActOnOpenMPDeclareSimdDirective(ArrayRef<OMPClause *> > >> >> Clauses, > >> >> + Decl *ADecl, > >> >> + > >> >> SourceLocation > >> >> StartLoc, > >> >> + bool > >> >> LastDirective); > >> >> + > >> >> OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind > >> >> Kind, > >> >> Expr *Expr, > >> >> SourceLocation > >> >> StartLoc, > >> >> Index: include/clang/AST/ASTMutationListener.h > >> >> =================================================================== > >> >> --- include/clang/AST/ASTMutationListener.h > >> >> +++ include/clang/AST/ASTMutationListener.h > >> >> @@ -113,6 +113,12 @@ > >> >> /// \param D the declaration marked OpenMP threadprivate. > >> >> virtual void DeclarationMarkedOpenMPThreadPrivate(const > >> >> Decl > >> >> *D) {} > >> >> > >> >> + /// \brief A declaration is marked as OpenMP declare simd > >> >> which > >> >> was not > >> >> + /// previously marked as declare simd. > >> >> + /// > >> >> + /// \param D the declaration marked OpenMP declare simd. > >> >> > >> >> Capitalize the first word in the documentation part of the > >> >> sentence. > >> >> > >> >> + virtual void DeclarationMarkedOpenMPDeclareSimd(const Decl > >> >> *D) > >> >> {} > >> >> + > >> >> /// \brief A definition has been made visible by being > >> >> redefined > >> >> locally. > >> >> /// > >> >> /// \param D The definition that was previously not > >> >> visible. > >> >> Index: include/clang/Parse/Parser.h > >> >> =================================================================== > >> >> --- include/clang/Parse/Parser.h > >> >> +++ include/clang/Parse/Parser.h > >> >> @@ -1019,6 +1019,19 @@ > >> >> CachedTokens *ExceptionSpecTokens; > >> >> }; > >> >> > >> >> + /// \brief An OpenMP declaration inside a class. > >> >> + struct LateParsedOpenMPDeclaration : public > >> >> LateParsedDeclaration { > >> >> + explicit LateParsedOpenMPDeclaration(Parser *P) : Self(P) > >> >> {} > >> >> + > >> >> + virtual void ParseLexedMethodDeclarations(); > >> >> > >> >> Drop the virtual, add override. > >> >> > >> >> + > >> >> + Parser *Self; > >> >> + > >> >> + /// \brief The set of tokens that make up an > >> >> exception-specification > >> >> that > >> >> + /// has not yet been parsed. > >> >> + CachedTokens Tokens; > >> >> + }; > >> >> + > >> >> /// LateParsedMemberInitializer - An initializer for a > >> >> non-static > >> >> class data > >> >> /// member whose parsing must to be delayed until the class > >> >> is > >> >> completely > >> >> /// defined (C++11 [class.mem]p2). > >> >> @@ -2364,7 +2377,13 @@ > >> >> > >> >> //===--------------------------------------------------------------------===// > >> >> // OpenMP: Directives and clauses. > >> >> /// \brief Parses declarative OpenMP directives. > >> >> - DeclGroupPtrTy ParseOpenMPDeclarativeDirective(); > >> >> + /// \param Level Current level of declarative directive, in > >> >> case if it > >> >> is > >> >> > >> >> Drop the "if" > >> >> > >> >> + /// allowed to apply multiple declarative directives to the > >> >> same > >> >> declaration. > >> >> + DeclGroupPtrTy ParseOpenMPDeclarativeDirective(bool > >> >> IsInTagDecl, > >> >> + unsigned > >> >> Level = > >> >> 0); > >> >> + /// \brief Late parse directive. > >> >> + void LateParseOpenMPDeclarativeDirective(OpenMPDirectiveKind > >> >> DKind, > >> >> + SourceLocation > >> >> Loc); > >> >> /// \brief Parses simple list of variables. > >> >> /// > >> >> /// \param Kind Kind of the directive. > >> >> Index: include/clang/Serialization/ASTWriter.h > >> >> =================================================================== > >> >> --- include/clang/Serialization/ASTWriter.h > >> >> +++ include/clang/Serialization/ASTWriter.h > >> >> @@ -859,6 +859,7 @@ > >> >> const ObjCCategoryDecl > >> >> *ClassExt) > >> >> override; > >> >> void DeclarationMarkedUsed(const Decl *D) override; > >> >> void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) > >> >> override; > >> >> + void DeclarationMarkedOpenMPDeclareSimd(const Decl *D) > >> >> override; > >> >> void RedefinedHiddenDefinition(const NamedDecl *D, Module > >> >> *M) > >> >> override; > >> >> }; > >> >> > >> >> Index: lib/Frontend/MultiplexConsumer.cpp > >> >> =================================================================== > >> >> --- lib/Frontend/MultiplexConsumer.cpp > >> >> +++ lib/Frontend/MultiplexConsumer.cpp > >> >> @@ -127,6 +127,7 @@ > >> >> const ObjCCategoryDecl > >> >> *ClassExt) > >> >> override; > >> >> void DeclarationMarkedUsed(const Decl *D) override; > >> >> void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) > >> >> override; > >> >> + void DeclarationMarkedOpenMPDeclareSimd(const Decl *D) > >> >> override; > >> >> void RedefinedHiddenDefinition(const NamedDecl *D, Module > >> >> *M) > >> >> override; > >> >> > >> >> private: > >> >> @@ -221,6 +222,11 @@ > >> >> for (size_t i = 0, e = Listeners.size(); i != e; ++i) > >> >> Listeners[i]->DeclarationMarkedOpenMPThreadPrivate(D); > >> >> } > >> >> +void > >> >> MultiplexASTMutationListener::DeclarationMarkedOpenMPDeclareSimd( > >> >> + const Decl *D) { > >> >> + for (size_t i = 0, e = Listeners.size(); i != e; ++i) > >> >> + Listeners[i]->DeclarationMarkedOpenMPDeclareSimd(D); > >> >> +} > >> >> > >> >> Can you use a range-based for loop please? > >> >> > >> >> void > >> >> MultiplexASTMutationListener::RedefinedHiddenDefinition(const > >> >> NamedDecl *D, > >> >> Module > >> >> *M) > >> >> { > >> >> for (auto *L : Listeners) > >> >> Index: lib/Basic/OpenMPKinds.cpp > >> >> =================================================================== > >> >> --- lib/Basic/OpenMPKinds.cpp > >> >> +++ lib/Basic/OpenMPKinds.cpp > >> >> @@ -324,6 +324,8 @@ > >> >> break; > >> >> } > >> >> break; > >> >> + case OMPD_declare_simd: > >> >> + break; > >> >> case OMPD_unknown: > >> >> case OMPD_threadprivate: > >> >> case OMPD_section: > >> >> Index: lib/Sema/SemaOpenMP.cpp > >> >> =================================================================== > >> >> --- lib/Sema/SemaOpenMP.cpp > >> >> +++ lib/Sema/SemaOpenMP.cpp > >> >> @@ -1283,6 +1283,7 @@ > >> >> case OMPD_barrier: > >> >> case OMPD_taskwait: > >> >> case OMPD_flush: > >> >> + case OMPD_declare_simd: > >> >> llvm_unreachable("OpenMP Directive is not allowed"); > >> >> case OMPD_unknown: > >> >> llvm_unreachable("Unknown OpenMP directive"); > >> >> @@ -1989,6 +1990,7 @@ > >> >> EndLoc); > >> >> break; > >> >> case OMPD_threadprivate: > >> >> + case OMPD_declare_simd: > >> >> llvm_unreachable("OpenMP Directive is not allowed"); > >> >> case OMPD_unknown: > >> >> llvm_unreachable("Unknown OpenMP directive"); > >> >> @@ -2006,6 +2008,34 @@ > >> >> return Res; > >> >> } > >> >> > >> >> +Sema::DeclGroupPtrTy > >> >> +Sema::ActOnOpenMPDeclareSimdDirective(ArrayRef<OMPClause *> > >> >> Clauses, > >> >> + Decl *ADecl, > >> >> SourceLocation > >> >> StartLoc, > >> >> + bool LastDirective) { > >> >> + if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl)) { > >> >> + ADecl = FTD->getTemplatedDecl(); > >> >> + } > >> >> > >> >> Elide braces. > >> >> > >> >> + if (!isa<FunctionDecl>(ADecl)) { > >> >> + Diag(ADecl->getLocation(), > >> >> diag::err_omp_function_expected) > >> >> + << ADecl->getDeclContext()->isFileContext(); > >> >> + return DeclGroupPtrTy(); > >> >> + } > >> >> + if (auto *Attr = ADecl->getAttr<OMPDeclareSimdDeclAttr>()) { > >> >> + if (!Attr->getComplete()) { > >> >> + > >> >> Attr->setNumberOfDirectives(Attr->getNumberOfDirectives() > >> >> + > >> >> 1); > >> >> + if (LastDirective) > >> >> + Attr->setComplete(); > >> >> + } > >> >> + } else { > >> >> + auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit( > >> >> + Context, 1, LastDirective, SourceRange(StartLoc, > >> >> StartLoc)); > >> >> > >> >> This is not an implicit attribute because it's the direct > >> >> result > >> >> of > >> >> the user typing something in source code. > >> >> > >> >> + ADecl->addAttr(NewAttr); > >> >> + if (auto *ML = Context.getASTMutationListener()) > >> >> + ML->DeclarationMarkedOpenMPDeclareSimd(ADecl); > >> >> + } > >> >> + return ConvertDeclToDeclGroup(ADecl); > >> >> +} > >> >> + > >> >> StmtResult > >> >> Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause > >> >> *> > >> >> Clauses, > >> >> Stmt *AStmt, > >> >> SourceLocation > >> >> StartLoc, > >> >> Index: lib/AST/DeclPrinter.cpp > >> >> =================================================================== > >> >> --- lib/AST/DeclPrinter.cpp > >> >> +++ lib/AST/DeclPrinter.cpp > >> >> @@ -36,6 +36,7 @@ > >> >> void ProcessDeclGroup(SmallVectorImpl<Decl*>& Decls); > >> >> > >> >> void Print(AccessSpecifier AS); > >> >> + void print(OMPDeclareSimdDeclAttr *A); > >> >> > >> >> /// Print an Objective-C method type in parentheses. > >> >> /// > >> >> @@ -405,7 +406,22 @@ > >> >> } > >> >> } > >> >> > >> >> +void DeclPrinter::print(OMPDeclareSimdDeclAttr *A) { > >> >> + for (unsigned i = 0; i < A->getNumberOfDirectives(); ++i) { > >> >> + A->printPrettyPragma(Out, Policy); > >> >> + Indent(); > >> >> + } > >> >> +} > >> >> + > >> >> void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { > >> >> + if (auto *Attr = D->getAttr<OMPDeclareSimdDeclAttr>()) { > >> >> + if (D->getTemplatedKind() != > >> >> + FunctionDecl::TK_FunctionTemplateSpecialization && > >> >> + D->getTemplatedKind() != > >> >> FunctionDecl::TK_FunctionTemplate && > >> >> + D->getTemplatedKind() != > >> >> + > >> >> FunctionDecl::TK_DependentFunctionTemplateSpecialization) > >> >> + print(Attr); > >> >> + } > >> >> CXXConstructorDecl *CDecl = > >> >> dyn_cast<CXXConstructorDecl>(D); > >> >> CXXConversionDecl *ConversionDecl = > >> >> dyn_cast<CXXConversionDecl>(D); > >> >> if (!Policy.SuppressSpecifiers) { > >> >> @@ -912,11 +928,17 @@ > >> >> if (PrintInstantiation) { > >> >> TemplateParameterList *Params = > >> >> D->getTemplateParameters(); > >> >> for (auto *I : D->specializations()) { > >> >> + if (auto *Attr = I->getAttr<OMPDeclareSimdDeclAttr>()) { > >> >> + print(Attr); > >> >> + } > >> >> > >> >> Elide braces. > >> >> > >> >> PrintTemplateParameters(Params, > >> >> I->getTemplateSpecializationArgs()); > >> >> Visit(I); > >> >> } > >> >> } > >> >> > >> >> + if (auto *Attr = > >> >> D->getTemplatedDecl()->getAttr<OMPDeclareSimdDeclAttr>()) { > >> >> + print(Attr); > >> >> + } > >> >> > >> >> Elide braces. > >> >> > >> >> return VisitRedeclarableTemplateDecl(D); > >> >> } > >> >> > >> >> Index: lib/Parse/ParseDeclCXX.cpp > >> >> =================================================================== > >> >> --- lib/Parse/ParseDeclCXX.cpp > >> >> +++ lib/Parse/ParseDeclCXX.cpp > >> >> @@ -2942,7 +2942,7 @@ > >> >> } > >> >> > >> >> if (Tok.is(tok::annot_pragma_openmp)) { > >> >> - ParseOpenMPDeclarativeDirective(); > >> >> + ParseOpenMPDeclarativeDirective(/*IsInTagDecl=*/true); > >> >> continue; > >> >> } > >> >> > >> >> Index: lib/Parse/ParseOpenMP.cpp > >> >> =================================================================== > >> >> --- lib/Parse/ParseOpenMP.cpp > >> >> +++ lib/Parse/ParseOpenMP.cpp > >> >> @@ -30,18 +30,26 @@ > >> >> // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd > >> >> // TODO: add other combined directives in topological > >> >> order. > >> >> const OpenMPDirectiveKind F[][3] = { > >> >> - { OMPD_for, OMPD_simd, OMPD_for_simd }, > >> >> - { OMPD_parallel, OMPD_for, OMPD_parallel_for }, > >> >> - { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, > >> >> - { OMPD_parallel, OMPD_sections, OMPD_parallel_sections } > >> >> + {OMPD_unknown /*declare*/, OMPD_simd, > >> >> OMPD_declare_simd}, > >> >> + {OMPD_for, OMPD_simd, OMPD_for_simd}, > >> >> + {OMPD_parallel, OMPD_for, OMPD_parallel_for}, > >> >> + {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, > >> >> + {OMPD_parallel, OMPD_sections, OMPD_parallel_sections} > >> >> }; > >> >> auto Tok = P.getCurToken(); > >> >> auto DKind = > >> >> Tok.isAnnotation() > >> >> ? OMPD_unknown > >> >> : > >> >> getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); > >> >> + bool TokenMatched = false; > >> >> for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { > >> >> - if (DKind == F[i][0]) { > >> >> + if (!Tok.isAnnotation() && DKind == OMPD_unknown) { > >> >> + TokenMatched = > >> >> + (i == 0) && > >> >> !P.getPreprocessor().getSpelling(Tok).compare("declare"); > >> >> + } else { > >> >> + TokenMatched = DKind == F[i][0]; > >> >> + } > >> >> > >> >> Elide braces. > >> >> > >> >> + if (TokenMatched) { > >> >> Tok = P.getPreprocessor().LookAhead(0); > >> >> auto SDKind = > >> >> Tok.isAnnotation() > >> >> @@ -61,13 +69,17 @@ > >> >> /// threadprivate-directive: > >> >> /// annot_pragma_openmp 'threadprivate' > >> >> simple-variable-list > >> >> /// > >> >> -Parser::DeclGroupPtrTy > >> >> Parser::ParseOpenMPDeclarativeDirective() > >> >> { > >> >> +Parser::DeclGroupPtrTy > >> >> +Parser::ParseOpenMPDeclarativeDirective(bool IsInTagDecl, > >> >> unsigned Level) > >> >> { > >> >> assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP > >> >> directive!"); > >> >> ParenBraceBracketBalancer BalancerRAIIObj(*this); > >> >> > >> >> + auto AnnotationVal = > >> >> reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()); > >> >> SourceLocation Loc = ConsumeToken(); > >> >> SmallVector<Expr *, 5> Identifiers; > >> >> - auto DKind = ParseOpenMPDirectiveKind(*this); > >> >> + OpenMPDirectiveKind DKind = > >> >> + (AnnotationVal == 0) ? ParseOpenMPDirectiveKind(*this) > >> >> + : > >> >> static_cast<OpenMPDirectiveKind>(AnnotationVal); > >> >> > >> >> switch (DKind) { > >> >> case OMPD_threadprivate: > >> >> @@ -85,6 +97,86 @@ > >> >> return Actions.ActOnOpenMPThreadprivateDirective(Loc, > >> >> Identifiers); > >> >> } > >> >> break; > >> >> + case OMPD_declare_simd: { > >> >> + // The syntax is: > >> >> + // { #pragma omp declare simd } > >> >> + // <function-declaration-or-definition> > >> >> + // > >> >> + if (AnnotationVal == 0) { > >> >> + // Skip 'simd' if it was restored from cached tokens. > >> >> + ConsumeToken(); > >> >> + } > >> >> > >> >> Elide braces. > >> >> > >> >> + if (IsInTagDecl) { > >> >> + > >> >> LateParseOpenMPDeclarativeDirective(/*DKind=*/OMPD_declare_simd, > >> >> Loc); > >> >> + return DeclGroupPtrTy(); > >> >> + } > >> >> + > >> >> + SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, > >> >> OMPC_unknown > >> >> + 1> > >> >> + FirstClauses(OMPC_unknown + 1); > >> >> + SmallVector<OMPClause *, 4> Clauses; > >> >> + SmallVector<Token, 8> CachedPragmas; > >> >> + > >> >> + while (Tok.isNot(tok::annot_pragma_openmp_end) && > >> >> Tok.isNot(tok::eof)) { > >> >> + CachedPragmas.push_back(Tok); > >> >> + ConsumeAnyToken(); > >> >> + } > >> >> + CachedPragmas.push_back(Tok); > >> >> + if (Tok.isNot(tok::eof)) > >> >> + ConsumeAnyToken(); > >> >> + > >> >> + DeclGroupPtrTy Ptr; > >> >> + if (Tok.is(tok::annot_pragma_openmp)) { > >> >> + Ptr = ParseOpenMPDeclarativeDirective(IsInTagDecl, Level > >> >> + > >> >> 1); > >> >> + } else { > >> >> + // Here we expect to see some function declaration. > >> >> + ParsedAttributesWithRange attrs(AttrFactory); > >> >> + MaybeParseCXX11Attributes(attrs); > >> >> + MaybeParseMicrosoftAttributes(attrs); > >> >> + ParsingDeclSpec PDS(*this); > >> >> + Ptr = ParseExternalDeclaration(attrs, &PDS); > >> >> > >> >> This really weirds me out. That means this function doesn't > >> >> parse > >> >> just > >> >> the pragma, it also parses any external declaration. > >> >> > >> >> + } > >> >> + if (!Ptr || Ptr.get().isNull()) > >> >> + return DeclGroupPtrTy(); > >> >> + if (Ptr.get().isDeclGroup()) { > >> >> + Diag(Tok, diag::err_omp_single_decl_in_declare_simd); > >> >> + return DeclGroupPtrTy(); > >> >> + } > >> >> + > >> >> + // Append the current token at the end of the new token > >> >> stream so > >> >> that it > >> >> + // doesn't get lost. > >> >> + CachedPragmas.push_back(Tok); > >> >> + // Push back tokens for pragma. > >> >> + PP.EnterTokenStream(CachedPragmas.data(), > >> >> CachedPragmas.size(), > >> >> + /*DisableMacroExpansion=*/true, > >> >> + /*OwnsTokens=*/false); > >> >> + // Parse pragma itself. > >> >> + // Consume the previously pushed token. > >> >> + ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); > >> >> + > >> >> + Actions.StartOpenMPClauses(); > >> >> + while (Tok.isNot(tok::annot_pragma_openmp_end)) { > >> >> + OpenMPClauseKind CKind = Tok.isAnnotation() > >> >> + ? OMPC_unknown > >> >> + : > >> >> getOpenMPClauseKind(PP.getSpelling(Tok)); > >> >> + OMPClause *Clause = > >> >> + ParseOpenMPClause(DKind, CKind, > >> >> !FirstClauses[CKind].getInt()); > >> >> + FirstClauses[CKind].setInt(true); > >> >> + if (Clause) { > >> >> + FirstClauses[CKind].setPointer(Clause); > >> >> + Clauses.push_back(Clause); > >> >> + } > >> >> + > >> >> + // Skip ',' if any. > >> >> + if (Tok.is(tok::comma)) > >> >> + ConsumeToken(); > >> >> + } > >> >> + Actions.EndOpenMPClauses(); > >> >> + // Consume final annot_pragma_openmp_end. > >> >> + ConsumeToken(); > >> >> + > >> >> + return Actions.ActOnOpenMPDeclareSimdDirective( > >> >> + Clauses, Ptr.get().getSingleDecl(), Loc, Level == 0); > >> >> + } > >> >> case OMPD_unknown: > >> >> Diag(Tok, diag::err_omp_unknown_directive); > >> >> break; > >> >> @@ -118,6 +210,69 @@ > >> >> return DeclGroupPtrTy(); > >> >> } > >> >> > >> >> +/// \brief Late parsing of declarative OpenMP directives. > >> >> +/// > >> >> +/// threadprivate-directive: > >> >> +/// annot_pragma_openmp 'threadprivate' > >> >> simple-variable-list > >> >> > >> >> The comments don't look correct here. > >> >> > >> >> +/// annot_pragma_openmp_end > >> >> +/// > >> >> +void > >> >> Parser::LateParseOpenMPDeclarativeDirective(OpenMPDirectiveKind > >> >> DKind, > >> >> + > >> >> SourceLocation > >> >> Loc) { > >> >> + if (DKind == OMPD_declare_simd) { > >> >> + LateParsedOpenMPDeclaration *Decl = new > >> >> LateParsedOpenMPDeclaration(this); > >> >> + getCurrentClass().LateParsedDeclarations.push_back(Decl); > >> >> + > >> >> + Token LocalTok; > >> >> + LocalTok.startToken(); > >> >> + LocalTok.setKind(tok::annot_pragma_openmp); > >> >> + LocalTok.setLocation(Loc); > >> >> + LocalTok.setAnnotationValue( > >> >> + reinterpret_cast<void > >> >> *>(static_cast<uintptr_t>(OMPD_declare_simd))); > >> >> + Decl->Tokens.push_back(LocalTok); > >> >> + > >> >> + do { > >> >> + while (Tok.isNot(tok::annot_pragma_openmp_end) && > >> >> Tok.isNot(tok::eof)) { > >> >> + Decl->Tokens.push_back(Tok); > >> >> + ConsumeAnyToken(); > >> >> + } > >> >> + Decl->Tokens.push_back(Tok); > >> >> + if (Tok.isNot(tok::eof)) > >> >> + ConsumeAnyToken(); > >> >> + } while (Tok.is(tok::annot_pragma_openmp)); > >> >> + > >> >> + LexTemplateFunctionForLateParsing(Decl->Tokens); > >> >> + } > >> >> +} > >> >> + > >> >> +/// \brief Actual parsing of late OpenMP declaration. > >> >> +void > >> >> Parser::LateParsedOpenMPDeclaration::ParseLexedMethodDeclarations() > >> >> { > >> >> + // Save the current token position. > >> >> + SourceLocation OrigLoc = Self->Tok.getLocation(); > >> >> + > >> >> + assert(!Tokens.empty() && "Empty body!"); > >> >> > >> >> Is this safe to assert in a parsing method, or should this be > >> >> diagnosed? > >> >> > >> >> + // Append the current token at the end of the new token > >> >> stream > >> >> so that > >> >> it > >> >> + // doesn't get lost. > >> >> + Tokens.push_back(Self->Tok); > >> >> + Self->PP.EnterTokenStream(Tokens.data(), Tokens.size(), > >> >> true, > >> >> false); > >> >> + > >> >> + // Consume the previously pushed token. > >> >> + Self->ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); > >> >> + > >> >> + > >> >> Self->ParseOpenMPDeclarativeDirective(/*IsInTagDecl=*/false); > >> >> + > >> >> + if (Self->Tok.getLocation() != OrigLoc) { > >> >> + // Due to parsing error, we either went over the cached > >> >> tokens or > >> >> + // there are still cached tokens left. If it's the latter > >> >> case skip > >> >> the > >> >> + // leftover tokens. > >> >> + // Since this is an uncommon situation that should be > >> >> avoided, use > >> >> the > >> >> + // expensive isBeforeInTranslationUnit call. > >> >> + if (Self->PP.getSourceManager().isBeforeInTranslationUnit( > >> >> + Self->Tok.getLocation(), OrigLoc)) > >> >> + while (Self->Tok.getLocation() != OrigLoc && > >> >> Self->Tok.isNot(tok::eof)) > >> >> + Self->ConsumeAnyToken(); > >> >> > >> >> Has this situation already been diagnosed? If so, then why are > >> >> we > >> >> generating the tokens in a way that require this work? And if > >> >> not, > >> >> are > >> >> we missing a diagnostic here? > >> >> > >> >> + } > >> >> +} > >> >> + > >> >> /// \brief Parsing of declarative or executable OpenMP > >> >> directives. > >> >> /// > >> >> /// threadprivate-directive: > >> >> @@ -274,6 +429,11 @@ > >> >> OMPDirectiveScope.Exit(); > >> >> break; > >> >> } > >> >> + case OMPD_declare_simd: > >> >> + Diag(Tok, diag::err_omp_unexpected_directive) > >> >> + << getOpenMPDirectiveName(DKind); > >> >> + SkipUntil(tok::annot_pragma_openmp_end); > >> >> + break; > >> >> case OMPD_unknown: > >> >> Diag(Tok, diag::err_omp_unknown_directive); > >> >> SkipUntil(tok::annot_pragma_openmp_end); > >> >> Index: lib/Parse/Parser.cpp > >> >> =================================================================== > >> >> --- lib/Parse/Parser.cpp > >> >> +++ lib/Parse/Parser.cpp > >> >> @@ -653,7 +653,7 @@ > >> >> HandlePragmaOpenCLExtension(); > >> >> return DeclGroupPtrTy(); > >> >> case tok::annot_pragma_openmp: > >> >> - return ParseOpenMPDeclarativeDirective(); > >> >> + return > >> >> ParseOpenMPDeclarativeDirective(/*IsInTagDecl=*/false); > >> >> case tok::annot_pragma_ms_pointers_to_members: > >> >> HandlePragmaMSPointersToMembers(); > >> >> return DeclGroupPtrTy(); > >> >> Index: lib/Serialization/ASTReaderDecl.cpp > >> >> =================================================================== > >> >> --- lib/Serialization/ASTReaderDecl.cpp > >> >> +++ lib/Serialization/ASTReaderDecl.cpp > >> >> @@ -3888,6 +3888,14 @@ > >> >> Reader.Context, ReadSourceRange(Record, Idx))); > >> >> break; > >> >> > >> >> + case UPD_DECL_MARKED_OPENMP_DECLARE_SIMD: { > >> >> + auto *Attr = OMPDeclareSimdDeclAttr::CreateImplicit( > >> >> + Reader.Context, Record[Idx++], Record[Idx++] != 0, > >> >> + ReadSourceRange(Record, Idx)); > >> >> > >> >> Attribute is not implicit. > >> >> > >> >> + D->addAttr(Attr); > >> >> + break; > >> >> + } > >> >> + > >> >> case UPD_DECL_EXPORTED: > >> >> unsigned SubmoduleID = readSubmoduleID(Record, Idx); > >> >> auto *Exported = cast<NamedDecl>(D); > >> >> Index: lib/Serialization/ASTCommon.h > >> >> =================================================================== > >> >> --- lib/Serialization/ASTCommon.h > >> >> +++ lib/Serialization/ASTCommon.h > >> >> @@ -36,6 +36,7 @@ > >> >> UPD_MANGLING_NUMBER, > >> >> UPD_STATIC_LOCAL_NUMBER, > >> >> UPD_DECL_MARKED_OPENMP_THREADPRIVATE, > >> >> + UPD_DECL_MARKED_OPENMP_DECLARE_SIMD, > >> >> UPD_DECL_EXPORTED > >> >> }; > >> >> > >> >> Index: lib/Serialization/ASTWriter.cpp > >> >> =================================================================== > >> >> --- lib/Serialization/ASTWriter.cpp > >> >> +++ lib/Serialization/ASTWriter.cpp > >> >> @@ -4615,6 +4615,14 @@ > >> >> Record); > >> >> break; > >> >> > >> >> + case UPD_DECL_MARKED_OPENMP_DECLARE_SIMD: { > >> >> + auto *Attr = D->getAttr<OMPDeclareSimdDeclAttr>(); > >> >> + AddSourceRange(Attr->getRange(), Record); > >> >> + Record.push_back(Attr->getNumberOfDirectives()); > >> >> + Record.push_back(Attr->getComplete() ? 1 : 0); > >> >> + break; > >> >> + } > >> >> + > >> >> case UPD_DECL_EXPORTED: > >> >> Record.push_back(getSubmoduleID(Update.getModule())); > >> >> break; > >> >> @@ -5761,6 +5769,14 @@ > >> >> > >> >> DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_THREADPRIVATE)); > >> >> } > >> >> > >> >> +void ASTWriter::DeclarationMarkedOpenMPDeclareSimd(const Decl > >> >> *D) > >> >> { > >> >> + assert(!WritingAST && "Already writing the AST!"); > >> >> + if (!D->isFromASTFile()) > >> >> + return; > >> >> + > >> >> + > >> >> DeclUpdates[D].push_back(DeclUpdate(UPD_DECL_MARKED_OPENMP_DECLARE_SIMD)); > >> >> +} > >> >> + > >> >> void ASTWriter::RedefinedHiddenDefinition(const NamedDecl *D, > >> >> Module *M) > >> >> { > >> >> assert(!WritingAST && "Already writing the AST!"); > >> >> assert(D->isHidden() && "expected a hidden declaration"); > >> > > >> > > >> > > > > -- > > Hal Finkel > > Assistant Computational Scientist > > Leadership Computing Facility > > Argonne National Laboratory > -- Hal Finkel Assistant Computational Scientist Leadership Computing Facility Argonne National Laboratory _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits