// gnu.ast            see license.txt for copyright and terms of use
// extension to cc.ast to support GNU language extensions

// sm: this contains both the representation language and the
// annotations used by the type checker, unlike the cc.ast
// vs. cc_tcheck.ast split, since there seemed little profit in that
// split for this file

verbatim {
  #define GNU_EXTENSION         // this extension module is active

  #include <limits.h>           // INT_MIN
}


// additional contexts in the GNU extensions
enum DeclaratorContext {
                          // inside ASTTypeId
  DC_TS_TYPEOF_TYPE,      //   TS_typeof_type::atype
  DC_E_COMPOUNDLIT,       //   E_compoundLit::stype
  DC_E_ALIGNOFTYPE,       //   E_alignofType::atype
  // DC_E_OFFSETOF,          //   E_offsetof::atype
  DC_E_BUILTIN_VA_ARG,    //   E___builtin_va_arg::atype
}


// The AST extensions in this file are organized in parallel with the
// syntactic extensions in gnu.gr.


// ----------- gcc statement expression -----------
class Expression {
  // statement-expression
  // http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Statement-Exprs.html
  -> E_statement(S_compound s) {
       // sort of like E_compoundLit::tcheckedType, this ensures we
       // only tcheck this once even though it might appear in
       // ambiguous contexts
       public bool tchecked = false;
     }
}


// ----------- gcc compound literals -----------
class Expression {
  // http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Compound-Literals.html
  // and C99 6.5.2.5
  -> E_compoundLit(ASTTypeId stype, IN_compound init) {
       // help for dealing with expressions being tchecked more than once
       public bool tcheckedType = false;
     }
}


// ----------- gcc misc -----------
class Statement {
  // nested function definition
  -> S_function(Function f);

  // case ranges
  -> S_rangeCase(Expression exprLo, Expression exprHi, Statement s) {
       public(xml) int labelValLo = 0;
       public(xml) int labelValHi = 0;
  }
}

class Expression {
  // miscellanous builtins that for whatever reason find themselves
  // as AST nodes instead of ordinary function calls (...)
  // http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Other-Builtins.html
  -> E___builtin_constant_p(Expression expr);

  // varargs; dsw: I think that we should make all of these their own
  // AST node, I just don't want to deal with the parsing ambiguity
  // with E_funCall right now
//   -> E___builtin_va_start(SourceLoc loc, Expression expr, Expression expr2);
//   -> E___builtin_va_copy(SourceLoc loc, Expression expr, Expression expr2);
  -> E___builtin_va_arg(Expression expr, ASTTypeId atype);
//   -> E___builtin_va_end(SourceLoc loc, Expression expr);

  // alignment inquiry
  // http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Alignment.html
  -> E_alignofType(ASTTypeId atype) {
       public virtual CValue extConstEval(ConstEval &env) const;
       public(xml) int alignment = 0; // set by tcheck
     }

  -> E_alignofExpr(Expression expr) {
       public virtual CValue extConstEval(ConstEval &env) const;
       public(xml) int alignment = 0;
     }

  // conditional with no middle operand
  // http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Conditionals.html
  -> E_gnuCond(Expression cond, Expression el) {
       public virtual CValue extConstEval(ConstEval &env) const;
       public virtual bool extHasUnparenthesizedGT();
     }

  // // quarl 2006-07-12
  // //    Handle __offsetof__ (gcc-3.4), __builtin_offsetof (gcc-4.x)
  // -> E_offsetof(ASTTypeId atype, PQName fieldName) {
  //      public virtual CValue extConstEval(ConstEval &env) const;
  //    }
}


// ----------- gcc dangling labels -----------
// (no AST extensions required)


// ----------- gcc typeof -----------
// types denoted with 'typeof' keyword
new class ASTTypeof {
  // same as we do for statements
  public ASTTypeof *ambiguity;  ctor ambiguity=NULL;
  public void addAmbiguity(ASTTypeof *alternative);
  custom traverse { if (ambiguity) ambiguity->traverse(vis); }

  // print ambiguities
  public void printAmbiguities(ostream &os, int indent) const;
  custom preemptDebugPrint {
    if (ambiguity) {
      printAmbiguities(os, indent);
      return;     // skip the normal, unambiguous-node print code
    }
  }

  // yield the ASTTypeof selected by ambiguity resolution; the
  // type is in its 'type' member
  public ASTTypeof *tcheck(Env &env, DeclFlags dflags);
  public void mid_tcheck(Env &env, DeclFlags &dflags);
  pure_virtual Type *itcheck(Env &env, DeclFlags dflags);

  // dsw: I had to move this here to deal with the mid_tcheck design
  // pattern that is used to resolve ambiguities.
  public(xml_TY) Type *type;

  // SGM 2007-08-25: TODO: I think the following two classes should
  // be renamed to begin with "ATO" rather than "TS".  The latter
  // incorrectly implies they are specializations of TypeSpecifier,
  // whereas in fact they are specializations of ASTTypeof.

  // dsw: I'm assuming that ASTTypeof should terminate the top of the
  // Expression tree, but I don't feel absolutely sure about it.
  -> TS_typeof_expr(FullExpression expr);

  -> TS_typeof_type(ASTTypeId atype);
}


class TypeSpecifier {
  -> TS_typeof(ASTTypeof atype);
  -> TS_classSpec 
  {
  public AttributeSpecifierList *alist=NULL;
  }

}


// ----------- gcc C++ min and max operators -----------
// (2005-04-07: there used to be a special E_gnuMinMax, but because
// those operators are overloadable, they become intertwined with much
// more of the tchecker structure, and therefore I folded them into
// BinaryOp)


// ----------- gcc asm -----------
// (no AST extension b/c extra info dropped on floor)


// ----------- gcc asm labels -----------
// (no AST extension b/c extra info dropped on floor)


// ----------- C99 designated initializers -----------
class Initializer {
  // a designator (list of fields/subscripts) in front of an
  // undesignated initializer
  -> IN_designated(FakeList<Designator> *designator_list,
                   Initializer init);
}

class Designator (SourceLoc loc) {
  // FakeList link; use setNext
  public Designator *next;  ctor next=NULL;
  public void setNext(Designator *newNext);

  // dsw: I seem to need all of this ambiguity stuff in order to use
  // genericSetNext

  // ambiguity representation
  public Designator *ambiguity; ctor ambiguity=NULL;
  public void addAmbiguity(Designator *alternative);
  custom traverse { if (ambiguity) ambiguity->traverse(vis); }

  // print ambiguities
  public void printAmbiguities(ostream &os, int indent) const;
  custom preemptDebugPrint {
    if (ambiguity) {
      printAmbiguities(os, indent);
      return;     // skip the normal, unambiguous-node print code
    }
  }

  pure_virtual void print(PrintEnv &env);

  -> FieldDesignator(StringRef id);

  -> SubscriptDesignator(Expression idx_expr, // taken from D_array
                         Expression /*nullable*/ idx_expr2)
  {
    public(xml) int idx_computed  = INT_MIN; // index computed at compile time
    public(xml) int idx_computed2 = INT_MIN; // index range end computed at compile time
  }
}


// ----------- C99 restrict keyword -----------
// (no AST extensions required b/c cc_flags.h already has *_RESTRICT)


// ----------- C99 qualifiers in array brackets -----------
// (no AST extension b/c extra info dropped on floor)


// ------------ gcc computed goto ----------
class Expression {
  // address of a label, e.g., "&&labelName"
  -> E_addrOfLabel(StringRef labelName);
}

class Statement {
  // goto a label whose address has been taken
  -> S_computedGoto(Expression target);
}


// ----------- gcc/C99 complex/imaginary ----------
class Expression {
  -> E_fieldAcc {
       // tcheck a __real__ or __imag__
       public Type *itcheck_complex_selector(Env &env, LookupFlags flags,
                                             LookupSet &candidates);
     }

  -> E_binary {
       // tcheck arith involving complex or imaginary types
       public Type *itcheck_complex_arith(Env &env);
     }
}


// ----------- gcc __attribute__ -----------
// For now, this is a very literal, parse-tree-like representation of
// attributes.  I don't know very much about how they will be used (I
// don't know much about what they *mean*), so it is hard to do any
// semantic digestion.  Therefore, I will not try.


// a sequence of __attribute__((..)) specifiers
class AttributeSpecifierList(
  AttributeSpecifier spec,
  AttributeSpecifierList /*nullable*/ next
);


// a single __attribute__((...)) specifier; there may be many
// individual attributes inside the parens
class AttributeSpecifier(
  Attribute attr,
  AttributeSpecifier /*nullable*/ next
);


// one attribute, somewhere inside __attribute((...)); syntactically,
// attributes are separated by commas in the parens
class Attribute(SourceLoc loc) {
  // e.g., __attribute__(( ))
  //                      ^
  // I decided to keep these even though the GNU documentation states
  // that they are always ignored, because it would be a bit awkward
  // to drop them in the parser, and they shouldn't occur frequently
  // anyway.
  -> AT_empty();

  // e.g., __attribute__((packed))
  //                      ^^^^^^
  // Note that even C++ keywords will just get stored as StringRefs.
  -> AT_word(StringRef w);

  // e.g., __attribute__((format(printf, 1, 2)))
  //                      ^^^^^^^^^^^^^^^^^^^^
  // the 'args' can be empty (NULL) to indicate an empty list (which
  // is still different from AT_word)
  -> AT_func(StringRef f, FakeList<ArgExpression> *args);
}


// Here's a clever idea: rather than making a completely new node to
// carry the attributes, I will inherit from D_grouping!  Then
// everyone will treat D_attribute like D_grouping, basically ignoring
// it, except the few pieces of code that want to know about it.  This
// seems much better than polluting the code with explicit knowledge
// of D_attribute.
//
// My astgen tool does not know how to introduce ad-hoc inheritance,
// so I will write this one by hand.
verbatim {
  // __attribute__ occurring directly after a declarator
  class D_attribute : public D_grouping {
  public:
    // NOTE: 'traverse' does *not* automatically go into this field,
    // because I want most clients to be oblivious to its presence.
    // They can explicitly intercept D_grouping and check for
    // D_attribute if traversal is desired.
    AttributeSpecifierList *alist;       // owner

  public:
    D_attribute(SourceLoc loc, IDeclarator *base,
                AttributeSpecifierList *alist);
    virtual ~D_attribute();

    virtual void debugPrint(ostream &os, int indent, char const *subtreeName = "tree") const;
    virtual void traverse(ASTVisitor &vis);

    virtual D_attribute *clone() const;

    virtual void tcheck(Env &env, Declarator::Tcheck &dt);

    // Return the attribute(alias("name")) name, or NULL if none.  There
    // mustn't be more than one.
    virtual StringRef getAlias() const;

  private:
    // Return the attribute alias, and check for errors
    StringRef tcheck_getAlias(Env *penv) const;
  };
}
// TODO: IDeclarator::isD_attribute(), asD_attribute(), ifD_attribute()

// EOF
