[flang] work around template specialization problem
authorpeter klausler <pklausler@nvidia.com>
Tue, 4 Dec 2018 23:52:50 +0000 (15:52 -0800)
committerpeter klausler <pklausler@nvidia.com>
Tue, 4 Dec 2018 23:52:50 +0000 (15:52 -0800)
Original-commit: flang-compiler/f18@1d67d72bea24a4ade66920527d2cc9104d2dfd48
Reviewed-on: https://github.com/flang-compiler/f18/pull/236

flang/lib/semantics/expression.cc
flang/lib/semantics/expression.h

index 03219f8..ae12fdf 100644 (file)
@@ -280,34 +280,18 @@ MaybeExpr AnalyzeExpr(
 // Catch-all unwrapper for AnalyzeExpr's most general case.
 template<typename A>
 MaybeExpr AnalyzeExpr(ExpressionAnalysisContext &context, const A &x) {
+  // Some compiler/version/option set combinations used to mysteriously
+  // overlook the template specialization in expression.h that
+  // redirected parser::Expr arguments, and they would arrive here
+  // in the catch-all template.  We've worked around that problem.
+  static_assert(
+      !std::is_same_v<A, parser::Expr>, "template specialization failed");
   return AnalyzeExpr(context, x.u);
 }
 
 // Definitions of AnalyzeExpr() specializations follow.
 // Helper subroutines are intermixed.
 
-// This specialization of AnalyzeExpr() constitutes the main entry point
-// to this module from the templates in expression.h.
-MaybeExpr AnalyzeExpr(
-    ExpressionAnalysisContext &context, const parser::Expr &expr) {
-  if (!expr.source.empty()) {
-    // Analyze the expression in a specified source position context for better
-    // error reporting.
-    auto save{
-        context.context().foldingContext().messages.SetLocation(expr.source)};
-    MaybeExpr result{AnalyzeExpr(context, expr.u)};
-    context.CheckConstraints(result);
-    return result;
-  } else {
-    MaybeExpr result{AnalyzeExpr(context, expr.u)};
-    context.CheckConstraints(result);
-    return result;
-  }
-}
-
-template MaybeExpr AnalyzeExpr(
-    ExpressionAnalysisContext &, const parser::Expr &);
-
 // Variants are silently traversed by AnalyzeExpr().
 template<typename... As>
 MaybeExpr AnalyzeExpr(
@@ -1478,6 +1462,21 @@ MaybeExpr AnalyzeExpr(
   context.Say("TODO: DefinedBinary unimplemented"_err_en_US);
   return std::nullopt;
 }
+
+MaybeExpr ExpressionAnalysisContext::Analyze(const parser::Expr &expr) {
+  if (!expr.source.empty()) {
+    // Analyze the expression in a specified source position context for better
+    // error reporting.
+    auto save{context_.foldingContext().messages.SetLocation(expr.source)};
+    MaybeExpr result{AnalyzeExpr(*this, expr.u)};
+    CheckConstraints(result);
+    return result;
+  } else {
+    MaybeExpr result{AnalyzeExpr(*this, expr.u)};
+    CheckConstraints(result);
+    return result;
+  }
+}
 }
 
 namespace Fortran::semantics {
index bfcf044..fcace3f 100644 (file)
@@ -74,6 +74,8 @@ public:
   bool LogicalConstraint(Expr<SomeType> &);
   bool DefaultCharConstraint(Expr<SomeType> &);
 
+  std::optional<Expr<SomeType>> Analyze(const parser::Expr &);
+
 protected:
   semantics::SemanticsContext &context_;
 
@@ -86,10 +88,11 @@ template<typename PARSED>
 std::optional<Expr<SomeType>> AnalyzeExpr(
     ExpressionAnalysisContext &, const PARSED &);
 
-// This extern template is the gateway into the rest of the expression
-// analysis implementation in expression.cc.
-extern template std::optional<Expr<SomeType>> AnalyzeExpr(
-    ExpressionAnalysisContext &, const parser::Expr &);
+template<>
+inline std::optional<Expr<SomeType>> AnalyzeExpr(
+    ExpressionAnalysisContext &context, const parser::Expr &expr) {
+  return context.Analyze(expr);
+}
 
 // Forward declarations of exposed specializations
 template<typename A>