[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Erich Keane via cfe-commits

https://github.com/erichkeane closed 
https://github.com/llvm/llvm-project/pull/90796
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Erich Keane via cfe-commits

https://github.com/erichkeane updated 
https://github.com/llvm/llvm-project/pull/90796

>From ac69522bf15c7c169c4cdb9d3d1547c5c0962193 Mon Sep 17 00:00:00 2001
From: erichkeane 
Date: Tue, 30 Apr 2024 11:42:35 -0700
Subject: [PATCH 1/2] [OpenACC} Implement SubArray Parsing/Sema

This implementation takes quite a bit from the OMP implementation of
array sections, but only has to enforce the rules as applicable to
OpenACC.  Additionally, it does its best to create an AST node (with the
assistance of RecoveryExprs) with as much checking done as soon as
possible in the case of instantiations.
---
 .../clang/Basic/DiagnosticSemaKinds.td|  24 +-
 clang/lib/Parse/ParseExpr.cpp |   3 +-
 clang/lib/Sema/SemaOpenACC.cpp| 232 ++-
 .../ParserOpenACC/parse-cache-construct.c |   3 +-
 .../ParserOpenACC/parse-cache-construct.cpp   |   8 +-
 clang/test/ParserOpenACC/parse-clauses.c  |   2 -
 clang/test/ParserOpenACC/parse-sub-array.cpp  |  89 +++
 .../compute-construct-private-clause.c|  26 +-
 .../compute-construct-private-clause.cpp  |   3 +-
 .../compute-construct-varlist-ast.cpp |   9 +
 clang/test/SemaOpenACC/sub-array-ast.cpp  | 566 ++
 clang/test/SemaOpenACC/sub-array.cpp  | 208 +++
 12 files changed, 1131 insertions(+), 42 deletions(-)
 create mode 100644 clang/test/ParserOpenACC/parse-sub-array.cpp
 create mode 100644 clang/test/SemaOpenACC/sub-array-ast.cpp
 create mode 100644 clang/test/SemaOpenACC/sub-array.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4b074b853bfe65..fbb107679d94ba 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12291,8 +12291,8 @@ def warn_acc_if_self_conflict
   "evaluates to true">,
   InGroup>;
 def err_acc_int_expr_requires_integer
-: Error<"OpenACC %select{clause|directive}0 '%1' requires expression of "
-"integer type (%2 invalid)">;
+: Error<"OpenACC %select{clause '%1'|directive '%2'|sub-array bound}0 "
+"requires expression of integer type (%3 invalid)">;
 def err_acc_int_expr_incomplete_class_type
 : Error<"OpenACC integer expression has incomplete class type %0">;
 def err_acc_int_expr_explicit_conversion
@@ -12310,4 +12310,24 @@ def err_acc_num_gangs_num_args
 def err_acc_not_a_var_ref
 : Error<"OpenACC variable is not a valid variable name, sub-array, array "
 "element, or composite variable member">;
+def err_acc_typecheck_subarray_value
+: Error<"OpenACC sub-array subscripted value is not an array or pointer">;
+def err_acc_subarray_function_type
+: Error<"OpenACC sub-array cannot be of function type %0">;
+def err_acc_subarray_incomplete_type
+: Error<"OpenACC sub-array base is of incomplete type %0">;
+def err_acc_subarray_no_length
+: Error<"OpenACC sub-array length is unspecified and cannot be inferred "
+"because the subscripted value is %select{not an array|an array of 
"
+"unknown bound}0">;
+def err_acc_subarray_negative
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to "
+"negative value %1">;
+def err_acc_subarray_out_of_range
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to a "
+"value (%1) that would be out of the range of the subscripted "
+"array size of %2">;
+def err_acc_subarray_base_plus_length_out_of_range
+: Error<"OpenACC sub-array specified range [%0:%1] would be out of the "
+"range of the subscripted array size of %2">;
 } // end of sema component.
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 7d6febb04a82c4..5f5f9a79c8c408 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2039,7 +2039,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
 if (Tok.is(tok::colon)) {
   // Consume ':'
   ColonLocFirst = ConsumeToken();
-  Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+  if (Tok.isNot(tok::r_square))
+Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
 }
   } else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {
 ColonProtectionRAIIObject RAII(*this);
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 3ea81e0497c203..a203ece7ff3130 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -16,6 +16,7 @@
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/OpenACCKinds.h"
 #include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Casting.h"
 
 using namespace clang;
@@ -367,7 +368,9 @@ ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind 
DK,
   assert(((DK != OpenACCDirectiveKind::Invalid &&
CK == 

[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Alexey Bataev via cfe-commits

https://github.com/alexey-bataev approved this pull request.

LG with a nit

https://github.com/llvm/llvm-project/pull/90796
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Alexey Bataev via cfe-commits


@@ -503,12 +512,211 @@ ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr 
*Base, SourceLocation LBLoc,
   SourceLocation RBLoc) {
   ASTContext  = getASTContext();
 
-  // TODO OpenACC: We likely have to reproduce a lot of the same logic from the
-  // OMP version of this, but at the moment we don't have a good way to test 
it,
-  // so for now we'll just create the node.
+  // Handle placeholders.
+  if (Base->hasPlaceholderType() &&
+  !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
+ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
+if (Result.isInvalid())
+  return ExprError();
+Base = Result.get();
+  }
+  if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
+ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
+if (Result.isInvalid())
+  return ExprError();
+Result = SemaRef.DefaultLvalueConversion(Result.get());
+if (Result.isInvalid())
+  return ExprError();
+LowerBound = Result.get();
+  }
+  if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
+ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
+if (Result.isInvalid())
+  return ExprError();
+Result = SemaRef.DefaultLvalueConversion(Result.get());
+if (Result.isInvalid())
+  return ExprError();
+Length = Result.get();
+  }
+
+  // Check the 'base' value, it must be an array or pointer type, and not to/of
+  // a function type.
+  QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base);
+  QualType ResultTy;
+  if (!Base->isTypeDependent()) {
+if (OriginalBaseTy->isAnyPointerType()) {
+  ResultTy = OriginalBaseTy->getPointeeType();
+} else if (OriginalBaseTy->isArrayType()) {
+  ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
+} else {
+  return ExprError(
+  Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
+  << Base->getSourceRange());
+}
+
+if (ResultTy->isFunctionType()) {
+  Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
+  << ResultTy << Base->getSourceRange();
+  return ExprError();
+}
+
+if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
+diag::err_acc_subarray_incomplete_type,
+Base))
+  return ExprError();
+
+if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
+  ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
+  if (Result.isInvalid())
+return ExprError();
+  Base = Result.get();
+}
+  }
+
+  auto GetRecovery = [&](Expr *E, QualType Ty) {
+ExprResult Recovery =
+SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), E, Ty);
+return Recovery.isUsable() ? Recovery.get() : nullptr;
+  };
+
+  // Ensure both of the expressions are int-exprs.
+  if (LowerBound && !LowerBound->isTypeDependent()) {
+ExprResult LBRes =
+ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
+ LowerBound->getExprLoc(), LowerBound);
+
+if (LBRes.isUsable())
+  LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
+LowerBound =
+LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, 
Context.IntTy);
+  }
+
+  if (Length && !Length->isTypeDependent()) {
+ExprResult LenRes =
+ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
+ Length->getExprLoc(), Length);
+
+if (LenRes.isUsable())
+  LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
+Length =
+LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
+  }
+
+  // Length is required if the base type is not an array of known bounds.
+  if (!Length && (OriginalBaseTy.isNull() ||
+  (!OriginalBaseTy->isDependentType() &&
+   !OriginalBaseTy->isConstantArrayType() &&
+   !OriginalBaseTy->isDependentSizedArrayType( {
+bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
+Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
+// Fill in a dummy 'length' so that when we instantiate this we don't
+// double-diagnose here.
+ExprResult Recovery = SemaRef.CreateRecoveryExpr(
+ColonLoc, SourceLocation(), ArrayRef{std::nullopt},
+Context.IntTy);
+Length = Recovery.isUsable() ? Recovery.get() : nullptr;
+  }
+
+  // Check the values of each of the arguments, they cannot be negative(we
+  // assume), and if the array bound is known, must be within range. As we do
+  // so, do our best to continue with evaluation, we can set the
+  // value/expression to nullptr/nullopt if they are invalid, and treat them as
+  // not present for the rest of evaluation.
+
+  // We don't have to check for dependence, because the dependent size is
+  // represented 

[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Alexey Bataev via cfe-commits

https://github.com/alexey-bataev edited 
https://github.com/llvm/llvm-project/pull/90796
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [OpenACC] Implement SubArray Parsing/Sema (PR #90796)

2024-05-02 Thread Alexey Bataev via cfe-commits

https://github.com/alexey-bataev edited 
https://github.com/llvm/llvm-project/pull/90796
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [OpenACC} Implement SubArray Parsing/Sema (PR #90796)

2024-05-01 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Erich Keane (erichkeane)


Changes

This implementation takes quite a bit from the OMP implementation of array 
sections, but only has to enforce the rules as applicable to OpenACC.  
Additionally, it does its best to create an AST node (with the assistance of 
RecoveryExprs) with as much checking done as soon as possible in the case of 
instantiations.

---

Patch is 60.81 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/90796.diff


12 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+22-2) 
- (modified) clang/lib/Parse/ParseExpr.cpp (+2-1) 
- (modified) clang/lib/Sema/SemaOpenACC.cpp (+220-12) 
- (modified) clang/test/ParserOpenACC/parse-cache-construct.c (+1-2) 
- (modified) clang/test/ParserOpenACC/parse-cache-construct.cpp (+4-4) 
- (modified) clang/test/ParserOpenACC/parse-clauses.c (-2) 
- (added) clang/test/ParserOpenACC/parse-sub-array.cpp (+89) 
- (modified) clang/test/SemaOpenACC/compute-construct-private-clause.c (+9-17) 
- (modified) clang/test/SemaOpenACC/compute-construct-private-clause.cpp (+1-2) 
- (modified) clang/test/SemaOpenACC/compute-construct-varlist-ast.cpp (+9) 
- (added) clang/test/SemaOpenACC/sub-array-ast.cpp (+566) 
- (added) clang/test/SemaOpenACC/sub-array.cpp (+208) 


``diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4b074b853bfe65..fbb107679d94ba 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12291,8 +12291,8 @@ def warn_acc_if_self_conflict
   "evaluates to true">,
   InGroup>;
 def err_acc_int_expr_requires_integer
-: Error<"OpenACC %select{clause|directive}0 '%1' requires expression of "
-"integer type (%2 invalid)">;
+: Error<"OpenACC %select{clause '%1'|directive '%2'|sub-array bound}0 "
+"requires expression of integer type (%3 invalid)">;
 def err_acc_int_expr_incomplete_class_type
 : Error<"OpenACC integer expression has incomplete class type %0">;
 def err_acc_int_expr_explicit_conversion
@@ -12310,4 +12310,24 @@ def err_acc_num_gangs_num_args
 def err_acc_not_a_var_ref
 : Error<"OpenACC variable is not a valid variable name, sub-array, array "
 "element, or composite variable member">;
+def err_acc_typecheck_subarray_value
+: Error<"OpenACC sub-array subscripted value is not an array or pointer">;
+def err_acc_subarray_function_type
+: Error<"OpenACC sub-array cannot be of function type %0">;
+def err_acc_subarray_incomplete_type
+: Error<"OpenACC sub-array base is of incomplete type %0">;
+def err_acc_subarray_no_length
+: Error<"OpenACC sub-array length is unspecified and cannot be inferred "
+"because the subscripted value is %select{not an array|an array of 
"
+"unknown bound}0">;
+def err_acc_subarray_negative
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to "
+"negative value %1">;
+def err_acc_subarray_out_of_range
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to a "
+"value (%1) that would be out of the range of the subscripted "
+"array size of %2">;
+def err_acc_subarray_base_plus_length_out_of_range
+: Error<"OpenACC sub-array specified range [%0:%1] would be out of the "
+"range of the subscripted array size of %2">;
 } // end of sema component.
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 7d6febb04a82c4..5f5f9a79c8c408 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2039,7 +2039,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
 if (Tok.is(tok::colon)) {
   // Consume ':'
   ColonLocFirst = ConsumeToken();
-  Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+  if (Tok.isNot(tok::r_square))
+Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
 }
   } else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {
 ColonProtectionRAIIObject RAII(*this);
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 3ea81e0497c203..a203ece7ff3130 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -16,6 +16,7 @@
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Basic/OpenACCKinds.h"
 #include "clang/Sema/Sema.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Casting.h"
 
 using namespace clang;
@@ -367,7 +368,9 @@ ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind 
DK,
   assert(((DK != OpenACCDirectiveKind::Invalid &&
CK == OpenACCClauseKind::Invalid) ||
   (DK == OpenACCDirectiveKind::Invalid &&
-   CK != OpenACCClauseKind::Invalid)) &&
+   CK != OpenACCClauseKind::Invalid) ||

[clang] [OpenACC} Implement SubArray Parsing/Sema (PR #90796)

2024-05-01 Thread Erich Keane via cfe-commits

https://github.com/erichkeane created 
https://github.com/llvm/llvm-project/pull/90796

This implementation takes quite a bit from the OMP implementation of array 
sections, but only has to enforce the rules as applicable to OpenACC.  
Additionally, it does its best to create an AST node (with the assistance of 
RecoveryExprs) with as much checking done as soon as possible in the case of 
instantiations.

>From ac69522bf15c7c169c4cdb9d3d1547c5c0962193 Mon Sep 17 00:00:00 2001
From: erichkeane 
Date: Tue, 30 Apr 2024 11:42:35 -0700
Subject: [PATCH] [OpenACC} Implement SubArray Parsing/Sema

This implementation takes quite a bit from the OMP implementation of
array sections, but only has to enforce the rules as applicable to
OpenACC.  Additionally, it does its best to create an AST node (with the
assistance of RecoveryExprs) with as much checking done as soon as
possible in the case of instantiations.
---
 .../clang/Basic/DiagnosticSemaKinds.td|  24 +-
 clang/lib/Parse/ParseExpr.cpp |   3 +-
 clang/lib/Sema/SemaOpenACC.cpp| 232 ++-
 .../ParserOpenACC/parse-cache-construct.c |   3 +-
 .../ParserOpenACC/parse-cache-construct.cpp   |   8 +-
 clang/test/ParserOpenACC/parse-clauses.c  |   2 -
 clang/test/ParserOpenACC/parse-sub-array.cpp  |  89 +++
 .../compute-construct-private-clause.c|  26 +-
 .../compute-construct-private-clause.cpp  |   3 +-
 .../compute-construct-varlist-ast.cpp |   9 +
 clang/test/SemaOpenACC/sub-array-ast.cpp  | 566 ++
 clang/test/SemaOpenACC/sub-array.cpp  | 208 +++
 12 files changed, 1131 insertions(+), 42 deletions(-)
 create mode 100644 clang/test/ParserOpenACC/parse-sub-array.cpp
 create mode 100644 clang/test/SemaOpenACC/sub-array-ast.cpp
 create mode 100644 clang/test/SemaOpenACC/sub-array.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4b074b853bfe65..fbb107679d94ba 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12291,8 +12291,8 @@ def warn_acc_if_self_conflict
   "evaluates to true">,
   InGroup>;
 def err_acc_int_expr_requires_integer
-: Error<"OpenACC %select{clause|directive}0 '%1' requires expression of "
-"integer type (%2 invalid)">;
+: Error<"OpenACC %select{clause '%1'|directive '%2'|sub-array bound}0 "
+"requires expression of integer type (%3 invalid)">;
 def err_acc_int_expr_incomplete_class_type
 : Error<"OpenACC integer expression has incomplete class type %0">;
 def err_acc_int_expr_explicit_conversion
@@ -12310,4 +12310,24 @@ def err_acc_num_gangs_num_args
 def err_acc_not_a_var_ref
 : Error<"OpenACC variable is not a valid variable name, sub-array, array "
 "element, or composite variable member">;
+def err_acc_typecheck_subarray_value
+: Error<"OpenACC sub-array subscripted value is not an array or pointer">;
+def err_acc_subarray_function_type
+: Error<"OpenACC sub-array cannot be of function type %0">;
+def err_acc_subarray_incomplete_type
+: Error<"OpenACC sub-array base is of incomplete type %0">;
+def err_acc_subarray_no_length
+: Error<"OpenACC sub-array length is unspecified and cannot be inferred "
+"because the subscripted value is %select{not an array|an array of 
"
+"unknown bound}0">;
+def err_acc_subarray_negative
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to "
+"negative value %1">;
+def err_acc_subarray_out_of_range
+: Error<"OpenACC sub-array %select{lower bound|length}0 evaluated to a "
+"value (%1) that would be out of the range of the subscripted "
+"array size of %2">;
+def err_acc_subarray_base_plus_length_out_of_range
+: Error<"OpenACC sub-array specified range [%0:%1] would be out of the "
+"range of the subscripted array size of %2">;
 } // end of sema component.
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 7d6febb04a82c4..5f5f9a79c8c408 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2039,7 +2039,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
 if (Tok.is(tok::colon)) {
   // Consume ':'
   ColonLocFirst = ConsumeToken();
-  Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+  if (Tok.isNot(tok::r_square))
+Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
 }
   } else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {
 ColonProtectionRAIIObject RAII(*this);
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 3ea81e0497c203..a203ece7ff3130 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -16,6 +16,7 @@
 #include "clang/Basic/DiagnosticSema.h"
 #include